@@ -171,7 +171,6 @@  | 
            ||
| 171 | 171 | 
                 		053E127521F5A72000A64893 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 053E127421F5A72000A64893 /* Error.swift */; };
               | 
            
| 172 | 172 | 
                 		053E127821F5B6E400A64893 /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 053E127721F5B6E400A64893 /* AlertController.swift */; };
               | 
            
| 173 | 173 | 
                 		0543E7F421CB911200A42807 /* UserInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E7F321CB911200A42807 /* UserInfoViewModel.swift */; };
               | 
            
| 174 | 
                -		0543E80721D0CDFA00A42807 /* MineFeedbackViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E80621D0CDFA00A42807 /* MineFeedbackViewModel.swift */; };
               | 
            |
| 175 | 174 | 
                 		0543E80B21D1DF4000A42807 /* GroupMemberItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E80A21D1DF4000A42807 /* GroupMemberItem.swift */; };
               | 
            
| 176 | 175 | 
                 		0543E80D21D1E2EA00A42807 /* PhotoGroupDetailRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E80C21D1E2EA00A42807 /* PhotoGroupDetailRepository.swift */; };
               | 
            
| 177 | 176 | 
                 		0543E80F21D1FD1100A42807 /* GroupDetailItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0543E80E21D1FD1100A42807 /* GroupDetailItem.swift */; };
               | 
            
                @@ -413,7 +412,6 @@  | 
            ||
| 413 | 412 | 
                 		0543274721C68C1900C6388D /* DateExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateExt.swift; sourceTree = "<group>"; };
               | 
            
| 414 | 413 | 
                 		0543276621C68C3300C6388D /* UIImageView+Kingfisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Kingfisher.swift"; sourceTree = "<group>"; };
               | 
            
| 415 | 414 | 
                 		0543E7F321CB911200A42807 /* UserInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoViewModel.swift; sourceTree = "<group>"; };
               | 
            
| 416 | 
                -		0543E80621D0CDFA00A42807 /* MineFeedbackViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineFeedbackViewModel.swift; sourceTree = "<group>"; };
               | 
            |
| 417 | 415 | 
                 		0543E80A21D1DF4000A42807 /* GroupMemberItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMemberItem.swift; sourceTree = "<group>"; };
               | 
            
| 418 | 416 | 
                 		0543E80C21D1E2EA00A42807 /* PhotoGroupDetailRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoGroupDetailRepository.swift; sourceTree = "<group>"; };
               | 
            
| 419 | 417 | 
                 		0543E80E21D1FD1100A42807 /* GroupDetailItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupDetailItem.swift; sourceTree = "<group>"; };
               | 
            
                @@ -948,7 +946,6 @@  | 
            ||
| 948 | 946 | 
                children = (  | 
            
| 949 | 947 | 
                42CF50451EC0526C00D23E9F /* MineGroupViewModel.swift */,  | 
            
| 950 | 948 | 
                42CF50471EC052B200D23E9F /* MineOrderViewModel.swift */,  | 
            
| 951 | 
                - 0543E80621D0CDFA00A42807 /* MineFeedbackViewModel.swift */,  | 
            |
| 952 | 949 | 
                );  | 
            
| 953 | 950 | 
                path = Mine;  | 
            
| 954 | 951 | 
                sourceTree = "<group>";  | 
            
                @@ -1710,7 +1707,6 @@  | 
            ||
| 1710 | 1707 | 
                057CA9CE21DDAE8100FB7D03 /* GroupDetailRepository.swift in Sources */,  | 
            
| 1711 | 1708 | 
                0543E80B21D1DF4000A42807 /* GroupMemberItem.swift in Sources */,  | 
            
| 1712 | 1709 | 
                0513103121CA1B67004EF1BE /* MessageRepository.swift in Sources */,  | 
            
| 1713 | 
                - 0543E80721D0CDFA00A42807 /* MineFeedbackViewModel.swift in Sources */,  | 
            |
| 1714 | 1710 | 
                0513103321CA1B67004EF1BE /* UserInfoRepository.swift in Sources */,  | 
            
| 1715 | 1711 | 
                0513103521CA1B67004EF1BE /* RecentGroupInfo.swift in Sources */,  | 
            
| 1716 | 1712 | 
                0513103921CA1B67004EF1BE /* HomeViewModel.swift in Sources */,  | 
            
                @@ -2,4 +2,16 @@  | 
            ||
| 2 | 2 | 
                <Bucket  | 
            
| 3 | 3 | 
                type = "1"  | 
            
| 4 | 4 | 
                version = "2.0">  | 
            
| 5 | 
                + <Breakpoints>  | 
            |
| 6 | 
                + <BreakpointProxy  | 
            |
| 7 | 
                + BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">  | 
            |
| 8 | 
                + <BreakpointContent  | 
            |
| 9 | 
                + shouldBeEnabled = "Yes"  | 
            |
| 10 | 
                + ignoreCount = "0"  | 
            |
| 11 | 
                + continueAfterRunningActions = "No"  | 
            |
| 12 | 
                + scope = "0"  | 
            |
| 13 | 
                + stopOnStyle = "0">  | 
            |
| 14 | 
                + </BreakpointContent>  | 
            |
| 15 | 
                + </BreakpointProxy>  | 
            |
| 16 | 
                + </Breakpoints>  | 
            |
| 5 | 17 | 
                </Bucket>  | 
            
                @@ -2,6 +2,7 @@  | 
            ||
| 2 | 2 | 
                "images" : [  | 
            
| 3 | 3 | 
                     {
               | 
            
| 4 | 4 | 
                "idiom" : "universal",  | 
            
| 5 | 
                + "filename" : "BTN-拍照.png",  | 
            |
| 5 | 6 | 
                "scale" : "1x"  | 
            
| 6 | 7 | 
                },  | 
            
| 7 | 8 | 
                     {
               | 
            
                @@ -10,7 +11,6 @@  | 
            ||
| 10 | 11 | 
                },  | 
            
| 11 | 12 | 
                     {
               | 
            
| 12 | 13 | 
                "idiom" : "universal",  | 
            
| 13 | 
                - "filename" : "BTN-拍照.png",  | 
            |
| 14 | 14 | 
                "scale" : "3x"  | 
            
| 15 | 15 | 
                }  | 
            
| 16 | 16 | 
                ],  | 
            
                @@ -2,6 +2,7 @@  | 
            ||
| 2 | 2 | 
                "images" : [  | 
            
| 3 | 3 | 
                     {
               | 
            
| 4 | 4 | 
                "idiom" : "universal",  | 
            
| 5 | 
                + "filename" : "delete.png",  | 
            |
| 5 | 6 | 
                "scale" : "1x"  | 
            
| 6 | 7 | 
                },  | 
            
| 7 | 8 | 
                     {
               | 
            
                @@ -10,7 +11,6 @@  | 
            ||
| 10 | 11 | 
                },  | 
            
| 11 | 12 | 
                     {
               | 
            
| 12 | 13 | 
                "idiom" : "universal",  | 
            
| 13 | 
                - "filename" : "delete.png",  | 
            |
| 14 | 14 | 
                "scale" : "3x"  | 
            
| 15 | 15 | 
                }  | 
            
| 16 | 16 | 
                ],  | 
            
                @@ -0,0 +1,21 @@  | 
            ||
| 1 | 
                +{
               | 
            |
| 2 | 
                + "images" : [  | 
            |
| 3 | 
                +    {
               | 
            |
| 4 | 
                + "idiom" : "universal",  | 
            |
| 5 | 
                + "filename" : "未命名设计.png",  | 
            |
| 6 | 
                + "scale" : "1x"  | 
            |
| 7 | 
                + },  | 
            |
| 8 | 
                +    {
               | 
            |
| 9 | 
                + "idiom" : "universal",  | 
            |
| 10 | 
                + "scale" : "2x"  | 
            |
| 11 | 
                + },  | 
            |
| 12 | 
                +    {
               | 
            |
| 13 | 
                + "idiom" : "universal",  | 
            |
| 14 | 
                + "scale" : "3x"  | 
            |
| 15 | 
                + }  | 
            |
| 16 | 
                + ],  | 
            |
| 17 | 
                +  "info" : {
               | 
            |
| 18 | 
                + "version" : 1,  | 
            |
| 19 | 
                + "author" : "xcode"  | 
            |
| 20 | 
                + }  | 
            |
| 21 | 
                +}  | 
            
      
                @@ -10,7 +10,6 @@ import Foundation  | 
            ||
| 10 | 10 | 
                import ObjectMapper  | 
            
| 11 | 11 | 
                import RxDataSources  | 
            
| 12 | 12 | 
                 | 
            
| 13 | 
                -  | 
            |
| 14 | 13 | 
                 public struct GroupItem: JSONCode {
               | 
            
| 15 | 14 | 
                public var create_at = ""  | 
            
| 16 | 15 | 
                public var created_at: Date?  | 
            
                @@ -23,6 +22,7 @@ public struct GroupItem: JSONCode {
               | 
            ||
| 23 | 22 | 
                public var group_id = ""  | 
            
| 24 | 23 | 
                public var group_avatar = ""  | 
            
| 25 | 24 | 
                public var group_photo_num = 0  | 
            
| 25 | 
                +  | 
            |
| 26 | 26 | 
                //tour group info  | 
            
| 27 | 27 | 
                public var gathered_at = ""  | 
            
| 28 | 28 | 
                public var gather_str = ""  | 
            
                @@ -69,13 +69,17 @@ extension GroupItem: Mappable {
               | 
            ||
| 69 | 69 | 
                gather_lat <- map["gather_lat"]  | 
            
| 70 | 70 | 
                gather_lon <- map["gather_lon"]  | 
            
| 71 | 71 | 
                gather_screenshot <- map["gather_screenshot"]  | 
            
| 72 | 
                - // gather_str = gather_at?.getTimeString(format: "HH点MM分")  | 
            |
| 73 | 
                -        guard let value = map["banners"].currentValue as? [String: Any] else {
               | 
            |
| 74 | 
                - return  | 
            |
| 72 | 
                +        if let value = map["banners"].currentValue as? [String: Any] {
               | 
            |
| 73 | 
                + let banner = Map(mappingType: MappingType.fromJSON, JSON: value)  | 
            |
| 74 | 
                + attentions <- banner["attentions"]  | 
            |
| 75 | 
                + schedules <- banner["schedules"]  | 
            |
| 76 | 
                + }  | 
            |
| 77 | 
                +  | 
            |
| 78 | 
                +        if let date = created_at {
               | 
            |
| 79 | 
                + let createDateFormatter = DateFormatter()  | 
            |
| 80 | 
                + createDateFormatter.dateFormat = "yyyy年MM月dd日 HH:mm"  | 
            |
| 81 | 
                + create_at = createDateFormatter.string(from: date)  | 
            |
| 75 | 82 | 
                }  | 
            
| 76 | 
                - let banner = Map(mappingType: MappingType.fromJSON, JSON: value)  | 
            |
| 77 | 
                - attentions <- banner["attentions"]  | 
            |
| 78 | 
                - schedules <- banner["schedules"]  | 
            |
| 79 | 83 | 
                }  | 
            
| 80 | 84 | 
                }  | 
            
| 81 | 85 | 
                 | 
            
                @@ -16,7 +16,8 @@ public struct PhotoCommentItem: JSONCode {
               | 
            ||
| 16 | 16 | 
                public var comment: String = ""  | 
            
| 17 | 17 | 
                public var user_id: String = ""  | 
            
| 18 | 18 | 
                public var nickname: String = ""  | 
            
| 19 | 
                - public var create_at: Date?  | 
            |
| 19 | 
                + public var created_at: Date?  | 
            |
| 20 | 
                + public var create_at: String = ""  | 
            |
| 20 | 21 | 
                 | 
            
| 21 | 22 | 
                     init(json: [String: AnyObject]) {
               | 
            
| 22 | 23 | 
                self.init(map: Map(mappingType: .fromJSON, JSON: json))  | 
            
                @@ -26,12 +27,16 @@ extension PhotoCommentItem: Mappable {
               | 
            ||
| 26 | 27 | 
                     mutating public func mapping(map: Map) {
               | 
            
| 27 | 28 | 
                let dateFormatter = DateFormatter()  | 
            
| 28 | 29 | 
                dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"  | 
            
| 29 | 
                - create_at <- (map["created_at"], DateFormatterTransform(dateFormatter:dateFormatter))  | 
            |
| 30 | 
                + created_at <- (map["created_at"], DateFormatterTransform(dateFormatter:dateFormatter))  | 
            |
| 30 | 31 | 
                avatar <- (map["avatar"])  | 
            
| 31 | 32 | 
                comment <- map["comment"]  | 
            
| 32 | 33 | 
                user_id <- map["user_id"]  | 
            
| 33 | 34 | 
                nickname <- (map["nickname"])  | 
            
| 34 | 35 | 
                comment <- map["comment"]  | 
            
| 36 | 
                +  | 
            |
| 37 | 
                +        if let date = created_at {
               | 
            |
| 38 | 
                + create_at = date.getTimeInfoFromDate()  | 
            |
| 39 | 
                + }  | 
            |
| 35 | 40 | 
                }  | 
            
| 36 | 41 | 
                 | 
            
| 37 | 42 | 
                     public init(map: Map) {
               | 
            
                @@ -18,7 +18,7 @@ struct GroupRemoteAPI {
               | 
            ||
| 18 | 18 | 
                 | 
            
| 19 | 19 | 
                     private func parse(_ json: JSON) -> NetworkArrayData<GroupItem>? {
               | 
            
| 20 | 20 | 
                         guard let data  = json["data"] as? [String: AnyObject] else { return nil }
               | 
            
| 21 | 
                - return NetworkArrayData.init(json: data, dataField: "groups")  | 
            |
| 21 | 
                + return NetworkArrayData(json: data, dataField: "groups")  | 
            |
| 22 | 22 | 
                }  | 
            
| 23 | 23 | 
                 | 
            
| 24 | 24 | 
                     private func parseGroup(_ json: JSON) -> GroupItem? {
               | 
            
                @@ -11,9 +11,9 @@ import RxSwift  | 
            ||
| 11 | 11 | 
                import RxCocoa  | 
            
| 12 | 12 | 
                 | 
            
| 13 | 13 | 
                 public protocol GroupDetailViewModelDelegate: class {
               | 
            
| 14 | 
                - func navigationToGroupMember(_ item: GroupDetailItem)  | 
            |
| 15 | 
                - func navigationToGroupNameModification(_ item: GroupDetailItem)  | 
            |
| 16 | 
                - func navigationToRootViewController()  | 
            |
| 14 | 
                + func navigateToGroupMember(_ item: GroupDetailItem)  | 
            |
| 15 | 
                + func navigateToGroupNameModification(_ item: GroupDetailItem)  | 
            |
| 16 | 
                + func navigateToRootViewController()  | 
            |
| 17 | 17 | 
                }  | 
            
| 18 | 18 | 
                 | 
            
| 19 | 19 | 
                 public class GroupDetailViewModel {
               | 
            
                @@ -68,14 +68,14 @@ public class GroupDetailViewModel {
               | 
            ||
| 68 | 68 | 
                var v = self.item.value  | 
            
| 69 | 69 | 
                v.group.group_lock = true  | 
            
| 70 | 70 | 
                self.item.accept(v)  | 
            
| 71 | 
                -            }) { (error) in
               | 
            |
| 72 | 
                -  | 
            |
| 73 | 
                - }.disposed(by: disposeBag)  | 
            |
| 71 | 
                + Toast.show(message: "群已锁定")  | 
            |
| 72 | 
                + }).disposed(by: disposeBag)  | 
            |
| 74 | 73 | 
                         } else {
               | 
            
| 75 | 74 | 
                             repository.unlock().subscribe(onCompleted: {
               | 
            
| 76 | 75 | 
                var v = self.item.value  | 
            
| 77 | 76 | 
                v.group.group_lock = false  | 
            
| 78 | 
                - }, onError: nil).disposed(by: disposeBag)  | 
            |
| 77 | 
                + Toast.show(message: "群未锁定")  | 
            |
| 78 | 
                + }).disposed(by: disposeBag)  | 
            |
| 79 | 79 | 
                }  | 
            
| 80 | 80 | 
                }  | 
            
| 81 | 81 | 
                 | 
            
                @@ -87,21 +87,24 @@ public class GroupDetailViewModel {
               | 
            ||
| 87 | 87 | 
                 | 
            
| 88 | 88 | 
                     public func quit() {
               | 
            
| 89 | 89 | 
                         guard item.value.group.admin_id != ShareUserId else {
               | 
            
| 90 | 
                + Toast.show(message: "群主不能退出群")  | 
            |
| 90 | 91 | 
                return  | 
            
| 91 | 92 | 
                }  | 
            
| 93 | 
                + Toast.showActivity(message: "正在退出群")  | 
            |
| 92 | 94 | 
                repository.quit()  | 
            
| 93 | 95 | 
                             .subscribe(onCompleted: {[unowned self] in
               | 
            
| 94 | 
                - self.delegate?.navigationToRootViewController()  | 
            |
| 96 | 
                + Toast.show(message: "退出群成功")  | 
            |
| 97 | 
                + self.delegate?.navigateToRootViewController()  | 
            |
| 95 | 98 | 
                }).disposed(by: disposeBag)  | 
            
| 96 | 99 | 
                }  | 
            
| 97 | 100 | 
                }  | 
            
| 98 | 101 | 
                 | 
            
| 99 | 102 | 
                 public extension GroupDetailViewModel {
               | 
            
| 100 | 
                -    func navigationToGroupMember() {
               | 
            |
| 101 | 
                - delegate?.navigationToGroupMember(item.value)  | 
            |
| 103 | 
                +    func navigateToGroupMember() {
               | 
            |
| 104 | 
                + delegate?.navigateToGroupMember(item.value)  | 
            |
| 102 | 105 | 
                }  | 
            
| 103 | 106 | 
                 | 
            
| 104 | 
                -    func navigationToGroupNameModification() {
               | 
            |
| 105 | 
                - delegate?.navigationToGroupNameModification(item.value)  | 
            |
| 107 | 
                +    func navigateToGroupNameModification() {
               | 
            |
| 108 | 
                + delegate?.navigateToGroupNameModification(item.value)  | 
            |
| 106 | 109 | 
                }  | 
            
| 107 | 110 | 
                }  | 
            
                @@ -33,8 +33,10 @@ public class GroupMemberViewModel {
               | 
            ||
| 33 | 33 | 
                }  | 
            
| 34 | 34 | 
                 | 
            
| 35 | 35 | 
                     public func removeMember(_ item: GroupMemberItem) {
               | 
            
| 36 | 
                + Toast.showActivity(message: "正在删除群成员")  | 
            |
| 36 | 37 | 
                repository.removeMember(userId: item.user_id)  | 
            
| 37 | 38 | 
                             .subscribe(onCompleted: {[unowned self] in
               | 
            
| 39 | 
                + Toast.showActivity(message: "群成员已删除")  | 
            |
| 38 | 40 | 
                var content = self.items.value  | 
            
| 39 | 41 | 
                                 content.removeAll(where: { $0.user_id == item.user_id })
               | 
            
| 40 | 42 | 
                self.items.accept(content)  | 
            
                @@ -25,6 +25,7 @@ public class GroupViewModel {
               | 
            ||
| 25 | 25 | 
                 | 
            
| 26 | 26 | 
                private var _isLoading = PublishSubject<Void>()  | 
            
| 27 | 27 | 
                private let items = BehaviorRelay<[PhotoItem]>(value: [])  | 
            
| 28 | 
                + private let _hasData = BehaviorRelay<Bool>(value: false)  | 
            |
| 28 | 29 | 
                 | 
            
| 29 | 30 | 
                public var groupItem: BehaviorRelay<GroupItem>  | 
            
| 30 | 31 | 
                 | 
            
                @@ -43,6 +44,10 @@ public class GroupViewModel {
               | 
            ||
| 43 | 44 | 
                     public var isLoading: Observable<Void> {
               | 
            
| 44 | 45 | 
                return _isLoading.asObservable()  | 
            
| 45 | 46 | 
                }  | 
            
| 47 | 
                +  | 
            |
| 48 | 
                +    public var hasData: Observable<Bool> {
               | 
            |
| 49 | 
                + return _hasData.asObservable()  | 
            |
| 50 | 
                + }  | 
            |
| 46 | 51 | 
                 | 
            
| 47 | 52 | 
                     public var contents: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
               | 
            
| 48 | 53 | 
                         return items.map({ model in
               | 
            
                @@ -64,6 +69,7 @@ public class GroupViewModel {
               | 
            ||
| 64 | 69 | 
                                 guard let `self` = self else { return }
               | 
            
| 65 | 70 | 
                self._isLoading.onNext(())  | 
            
| 66 | 71 | 
                self.items.accept(result)  | 
            
| 72 | 
                + self._hasData.accept(result.count > 0)  | 
            |
| 67 | 73 | 
                                 }, onError: {[weak self] (error) in
               | 
            
| 68 | 74 | 
                                     guard let `self` = self else { return }
               | 
            
| 69 | 75 | 
                self._isLoading.onNext(())  | 
            
                @@ -71,12 +77,15 @@ public class GroupViewModel {
               | 
            ||
| 71 | 77 | 
                }  | 
            
| 72 | 78 | 
                 | 
            
| 73 | 79 | 
                     public func submit(data: Data) {
               | 
            
| 80 | 
                + Toast.showActivity(message: "正在上传照片")  | 
            |
| 74 | 81 | 
                         repository.upload(data: data).subscribe(onSuccess: { [weak self] result in
               | 
            
| 75 | 82 | 
                             guard let `self` = self else { return }
               | 
            
| 76 | 83 | 
                self.items.accept(result)  | 
            
| 84 | 
                + Toast.show(message: "照片已上传")  | 
            |
| 77 | 85 | 
                self._isLoading.onNext(())  | 
            
| 78 | 86 | 
                         }) {[weak self] (error) in
               | 
            
| 79 | 87 | 
                             guard let  `self` = self else { return }
               | 
            
| 88 | 
                + Toast.show(message: "照片失败")  | 
            |
| 80 | 89 | 
                self._isLoading.onNext(())  | 
            
| 81 | 90 | 
                }.disposed(by: disposeBag)  | 
            
| 82 | 91 | 
                }  | 
            
                @@ -11,7 +11,7 @@ import RxSwift  | 
            ||
| 11 | 11 | 
                import RxCocoa  | 
            
| 12 | 12 | 
                 | 
            
| 13 | 13 | 
                 public protocol CreateGroupViewModelDelegate: class {
               | 
            
| 14 | 
                - func navigationToGroup(_ item: GroupItem)  | 
            |
| 14 | 
                + func navigateToGroup(_ item: GroupItem)  | 
            |
| 15 | 15 | 
                }  | 
            
| 16 | 16 | 
                 | 
            
| 17 | 17 | 
                 public final class CreateGroupViewModel {
               | 
            
                @@ -40,9 +40,11 @@ public final class CreateGroupViewModel {
               | 
            ||
| 40 | 40 | 
                }  | 
            
| 41 | 41 | 
                 | 
            
| 42 | 42 | 
                     public func createGroup() {
               | 
            
| 43 | 
                + Toast.showActivity(message: "正在创建群")  | 
            |
| 43 | 44 | 
                return repository.create(groupName: name, avatar: "\(mappingIndex)")  | 
            
| 44 | 45 | 
                             .subscribe(onSuccess: {[unowned self] item in
               | 
            
| 45 | 
                - self.delegate?.navigationToGroup(item)  | 
            |
| 46 | 
                + Toast.show(message: "照片分享群已创建")  | 
            |
| 47 | 
                + self.delegate?.navigateToGroup(item)  | 
            |
| 46 | 48 | 
                }).disposed(by: disposeBag)  | 
            
| 47 | 49 | 
                }  | 
            
| 48 | 50 | 
                }  | 
            
                @@ -7,16 +7,18 @@  | 
            ||
| 7 | 7 | 
                //  | 
            
| 8 | 8 | 
                 | 
            
| 9 | 9 | 
                import Foundation  | 
            
| 10 | 
                +import RxSwift  | 
            |
| 10 | 11 | 
                 | 
            
| 11 | 
                -protocol ScanQRViewModelDelegate: class {
               | 
            |
| 12 | 
                - func navigateToGroupPage(item: GroupItem)  | 
            |
| 12 | 
                +public protocol ScanQRViewModelDelegate: class {
               | 
            |
| 13 | 
                + func navigateToGroupFromScanQR(_ item: GroupItem)  | 
            |
| 13 | 14 | 
                }  | 
            
| 14 | 15 | 
                 | 
            
| 15 | 16 | 
                 public final class ScanQRViewModel {
               | 
            
| 16 | 17 | 
                 | 
            
| 17 | 
                - weak var delegate: ScanQRViewModelDelegate?  | 
            |
| 18 | 
                + public weak var delegate: ScanQRViewModelDelegate?  | 
            |
| 18 | 19 | 
                 | 
            
| 19 | 20 | 
                var repository: PhotoGroupRepository  | 
            
| 21 | 
                + var disposeBag = DisposeBag()  | 
            |
| 20 | 22 | 
                 | 
            
| 21 | 23 | 
                     public init() {
               | 
            
| 22 | 24 | 
                repository = PhotoGroupRepository()  | 
            
                @@ -26,15 +28,24 @@ public final class ScanQRViewModel {
               | 
            ||
| 26 | 28 | 
                let strs = code.components(separatedBy: "/")  | 
            
| 27 | 29 | 
                         guard strs.count > 2, let params = strs.last else { return }
               | 
            
| 28 | 30 | 
                let flag = strs[strs.count - 2]  | 
            
| 31 | 
                +  | 
            |
| 29 | 32 | 
                         switch flag {
               | 
            
| 30 | 33 | 
                case "s":  | 
            
| 31 | 34 | 
                guard let lensman_id = params.components(separatedBy: "=").last,  | 
            
| 32 | 35 | 
                                 let session_id = params.components(separatedBy: "?").first else { return }
               | 
            
| 33 | 36 | 
                 | 
            
| 34 | 
                - repository.join(type: .session, parameter: ["session_id": session_id, "lensman_id": lensman_id])  | 
            |
| 37 | 
                + repository.join(type: .session,  | 
            |
| 38 | 
                + parameter: ["session_id": session_id, "lensman_id": lensman_id])  | 
            |
| 39 | 
                +                .subscribe(onSuccess: { item in
               | 
            |
| 40 | 
                + self.delegate?.navigateToGroupFromScanQR(item)  | 
            |
| 41 | 
                + }).disposed(by: disposeBag)  | 
            |
| 35 | 42 | 
                 | 
            
| 36 | 43 | 
                case "g":  | 
            
| 37 | 
                - repository.join(type: .session, parameter: ["group_id": params])  | 
            |
| 44 | 
                + repository.join(type: .group,  | 
            |
| 45 | 
                + parameter: ["group_id": params])  | 
            |
| 46 | 
                +                .subscribe(onSuccess: { item in
               | 
            |
| 47 | 
                + self.delegate?.navigateToGroupFromScanQR(item)  | 
            |
| 48 | 
                + }).disposed(by: disposeBag)  | 
            |
| 38 | 49 | 
                default:  | 
            
| 39 | 50 | 
                return  | 
            
| 40 | 51 | 
                }  | 
            
                @@ -92,23 +92,25 @@ public class MessageListViewModel {
               | 
            ||
| 92 | 92 | 
                }  | 
            
| 93 | 93 | 
                 | 
            
| 94 | 94 | 
                     public func remove(of index: Int) {
               | 
            
| 95 | 
                + Toast.showActivity(message: "正在删除这条消息")  | 
            |
| 95 | 96 | 
                repository.remove(type, pk: items.value[index].pk)  | 
            
| 96 | 97 | 
                             .subscribe(onCompleted: {[weak self] in
               | 
            
| 97 | 98 | 
                                 guard let `self` = self else { return }
               | 
            
| 98 | 99 | 
                var _items = self.items.value  | 
            
| 99 | 100 | 
                _items.remove(at: index)  | 
            
| 100 | 101 | 
                self.items.accept(_items)  | 
            
| 101 | 
                -                self._showMessage.onNext("删除成功")
               | 
            |
| 102 | 
                +                self._showMessage.onNext("消息删除")
               | 
            |
| 102 | 103 | 
                }).disposed(by: disposeBag)  | 
            
| 103 | 104 | 
                }  | 
            
| 104 | 105 | 
                 | 
            
| 105 | 106 | 
                     public func removeAll() {
               | 
            
| 107 | 
                + Toast.showActivity(message: "正在删除全部消息")  | 
            |
| 106 | 108 | 
                repository.removeAll(type)  | 
            
| 107 | 109 | 
                             .subscribe(onCompleted: {[weak self] in
               | 
            
| 108 | 110 | 
                                 guard let `self` = self else { return }
               | 
            
| 109 | 111 | 
                self.items.accept([])  | 
            
| 110 | 112 | 
                self._isEmpty.accept(false)  | 
            
| 111 | 
                -                self._showMessage.onNext("删除成功")
               | 
            |
| 113 | 
                +                self._showMessage.onNext("消息已清空")
               | 
            |
| 112 | 114 | 
                }).disposed(by: disposeBag)  | 
            
| 113 | 115 | 
                }  | 
            
| 114 | 116 | 
                 | 
            
                @@ -1,24 +0,0 @@  | 
            ||
| 1 | 
                -//  | 
            |
| 2 | 
                -// MineFeedbackViewModel.swift  | 
            |
| 3 | 
                -// PaiaiDataKit  | 
            |
| 4 | 
                -//  | 
            |
| 5 | 
                -// Created by ffib on 2018/12/24.  | 
            |
| 6 | 
                -// Copyright © 2018 yb. All rights reserved.  | 
            |
| 7 | 
                -//  | 
            |
| 8 | 
                -  | 
            |
| 9 | 
                -import Foundation  | 
            |
| 10 | 
                -  | 
            |
| 11 | 
                -protocol MineFeedbackViewModelDelegate: class {
               | 
            |
| 12 | 
                - func back()  | 
            |
| 13 | 
                -}  | 
            |
| 14 | 
                -  | 
            |
| 15 | 
                -class MineFeedbackViewModel {
               | 
            |
| 16 | 
                - weak var delegate: MineFeedbackViewModelDelegate?  | 
            |
| 17 | 
                - var api = FeedbackRemoteAPI()  | 
            |
| 18 | 
                -  | 
            |
| 19 | 
                -    func submit(_ text: String) {
               | 
            |
| 20 | 
                -        api.submit(text: text).subscribe(onCompleted: {
               | 
            |
| 21 | 
                - self.delegate?.back()  | 
            |
| 22 | 
                - }).dispose()  | 
            |
| 23 | 
                - }  | 
            |
| 24 | 
                -}  | 
            
                @@ -87,13 +87,14 @@ public class MineGroupViewModel {
               | 
            ||
| 87 | 87 | 
                }  | 
            
| 88 | 88 | 
                 | 
            
| 89 | 89 | 
                     public func remove(of index: Int) {
               | 
            
| 90 | 
                + Toast.showActivity(message: "正在删除此群")  | 
            |
| 90 | 91 | 
                repository.remove(groupId: items.value[index].group_id)  | 
            
| 91 | 92 | 
                             .subscribe(onCompleted: {[weak self] in
               | 
            
| 92 | 93 | 
                                 guard let `self` = self else { return }
               | 
            
| 93 | 94 | 
                var _items = self.items.value  | 
            
| 94 | 95 | 
                _items.remove(at: index)  | 
            
| 95 | 96 | 
                self.items.accept(_items)  | 
            
| 96 | 
                -                self._showMessage.onNext("删除成功")
               | 
            |
| 97 | 
                +                self._showMessage.onNext("群已删除")
               | 
            |
| 97 | 98 | 
                }).disposed(by: disposeBag)  | 
            
| 98 | 99 | 
                }  | 
            
| 99 | 100 | 
                 | 
            
                @@ -32,11 +32,18 @@ public class Toast {
               | 
            ||
| 32 | 32 | 
                }  | 
            
| 33 | 33 | 
                }  | 
            
| 34 | 34 | 
                 | 
            
| 35 | 
                +    public enum AnimationDuration {
               | 
            |
| 36 | 
                + case none  | 
            |
| 37 | 
                + case duration(TimeInterval)  | 
            |
| 38 | 
                + }  | 
            |
| 39 | 
                +  | 
            |
| 35 | 40 | 
                     public struct Config {
               | 
            
| 36 | 41 | 
                         public init() {}
               | 
            
| 37 | 42 | 
                 | 
            
| 38 | 43 | 
                         public var toastType: ToastType = .text("")
               | 
            
| 39 | 44 | 
                public var presentationStyle: PresentationStyle = .center  | 
            
| 45 | 
                + public var duration: AnimationDuration = .duration(1)  | 
            |
| 46 | 
                + public var option: ToastOption = .default  | 
            |
| 40 | 47 | 
                 | 
            
| 41 | 48 | 
                         public static var `default`: Config {
               | 
            
| 42 | 49 | 
                return Config()  | 
            
                @@ -45,17 +52,37 @@ public class Toast {
               | 
            ||
| 45 | 52 | 
                 | 
            
| 46 | 53 | 
                private var _toastView: ToastView?  | 
            
| 47 | 54 | 
                private var _config: Config = .default  | 
            
| 48 | 
                -  | 
            |
| 49 | 
                -  | 
            |
| 55 | 
                + private var _task: DispatchWorkItem?  | 
            |
| 50 | 56 | 
                }  | 
            
| 51 | 57 | 
                 | 
            
| 52 | 58 | 
                /// MARK: - APIS  | 
            
| 53 | 59 | 
                 public extension Toast {
               | 
            
| 54 | 60 | 
                     func show(config: Config = .default, in view: UIView? = UIApplication.shared.keyWindow) {
               | 
            
| 55 | 
                - let toastView = ToastView(option: .default, type: config.toastType)  | 
            |
| 56 | 
                - view?.addSubview(toastView)  | 
            |
| 57 | 
                - self._toastView = toastView  | 
            |
| 58 | 
                - showAnimation()  | 
            |
| 61 | 
                + self._config = config  | 
            |
| 62 | 
                +        if _toastView == nil {
               | 
            |
| 63 | 
                + let toastView = ToastView(option: config.option, type: config.toastType)  | 
            |
| 64 | 
                + view?.addSubview(toastView)  | 
            |
| 65 | 
                + _toastView = toastView  | 
            |
| 66 | 
                + showAnimation()  | 
            |
| 67 | 
                +        } else {
               | 
            |
| 68 | 
                +            if case let .duration(interval) = config.duration {
               | 
            |
| 69 | 
                +                if let task = _task {
               | 
            |
| 70 | 
                + let _ = task.wait(timeout: .now() + interval)  | 
            |
| 71 | 
                +                } else {
               | 
            |
| 72 | 
                +                    self._task = DispatchWorkItem(block: {
               | 
            |
| 73 | 
                + self.hideAnimation()  | 
            |
| 74 | 
                + })  | 
            |
| 75 | 
                + DispatchQueue.main.asyncAfter(deadline: .now() + interval, execute: self._task!)  | 
            |
| 76 | 
                + }  | 
            |
| 77 | 
                +            } else {
               | 
            |
| 78 | 
                + _task?.cancel()  | 
            |
| 79 | 
                + _task = nil  | 
            |
| 80 | 
                + }  | 
            |
| 81 | 
                +  | 
            |
| 82 | 
                + _toastView?.option = config.option  | 
            |
| 83 | 
                + _toastView?.toastType = config.toastType  | 
            |
| 84 | 
                + _toastView?.switchToast()  | 
            |
| 85 | 
                + }  | 
            |
| 59 | 86 | 
                }  | 
            
| 60 | 87 | 
                 | 
            
| 61 | 88 | 
                     func show(message: String, in view: UIView? = UIApplication.shared.keyWindow) {
               | 
            
                @@ -79,6 +106,7 @@ public extension Toast {
               | 
            ||
| 79 | 106 | 
                     func showActivity(message: String?, in view: UIView? = UIApplication.shared.keyWindow) {
               | 
            
| 80 | 107 | 
                var config = Config()  | 
            
| 81 | 108 | 
                config.toastType = .activityIndicator(message)  | 
            
| 109 | 
                + config.duration = .none  | 
            |
| 82 | 110 | 
                show(config: config, in: view)  | 
            
| 83 | 111 | 
                }  | 
            
| 84 | 112 | 
                 | 
            
                @@ -90,9 +118,16 @@ public extension Toast {
               | 
            ||
| 90 | 118 | 
                         guard let _toastView = _toastView else { return }
               | 
            
| 91 | 119 | 
                         _config.presentationStyle.animator.toastIn(in: _toastView) {[weak self] _ in
               | 
            
| 92 | 120 | 
                             guard let `self` = self else { return }
               | 
            
| 93 | 
                -            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
               | 
            |
| 94 | 
                - self.hide()  | 
            |
| 95 | 
                - })  | 
            |
| 121 | 
                +            switch self._config.duration {
               | 
            |
| 122 | 
                + case .none:  | 
            |
| 123 | 
                + break  | 
            |
| 124 | 
                + case let .duration(interval):  | 
            |
| 125 | 
                +                self._task = DispatchWorkItem(block: {
               | 
            |
| 126 | 
                + self.hideAnimation()  | 
            |
| 127 | 
                + })  | 
            |
| 128 | 
                + DispatchQueue.main.asyncAfter(deadline: .now() + interval, execute: self._task!)  | 
            |
| 129 | 
                + break  | 
            |
| 130 | 
                + }  | 
            |
| 96 | 131 | 
                }  | 
            
| 97 | 132 | 
                }  | 
            
| 98 | 133 | 
                 | 
            
                @@ -100,9 +135,15 @@ public extension Toast {
               | 
            ||
| 100 | 135 | 
                         guard let _toastView = _toastView else { return }
               | 
            
| 101 | 136 | 
                         _config.presentationStyle.animator.toastOut(in: _toastView) {[weak self] (flag) in
               | 
            
| 102 | 137 | 
                             guard let `self` = self else { return }
               | 
            
| 103 | 
                - self._toastView?.removeFromSuperview()  | 
            |
| 138 | 
                + self.clear()  | 
            |
| 104 | 139 | 
                }  | 
            
| 105 | 140 | 
                }  | 
            
| 141 | 
                +  | 
            |
| 142 | 
                +    private func clear() {
               | 
            |
| 143 | 
                + _toastView?.removeFromSuperview()  | 
            |
| 144 | 
                + _toastView = nil  | 
            |
| 145 | 
                + _task = nil  | 
            |
| 146 | 
                + }  | 
            |
| 106 | 147 | 
                }  | 
            
| 107 | 148 | 
                 | 
            
| 108 | 149 | 
                /// MARK: - Static APIS  | 
            
                @@ -10,7 +10,7 @@ import UIKit  | 
            ||
| 10 | 10 | 
                 | 
            
| 11 | 11 | 
                 public struct ToastOption {
               | 
            
| 12 | 12 | 
                var tintColor: UIColor = UIColor.white  | 
            
| 13 | 
                - var backgroundColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)  | 
            |
| 13 | 
                + var backgroundColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)  | 
            |
| 14 | 14 | 
                var font: UIFont = UIFont.systemFont(ofSize: 14)  | 
            
| 15 | 15 | 
                 | 
            
| 16 | 16 | 
                     public static var `default`: ToastOption {
               | 
            
                @@ -10,9 +10,11 @@ import UIKit  | 
            ||
| 10 | 10 | 
                 | 
            
| 11 | 11 | 
                 class ToastView: UIView {
               | 
            
| 12 | 12 | 
                 | 
            
| 13 | 
                - fileprivate var option: ToastOption  | 
            |
| 14 | 
                - fileprivate var toastType: Toast.ToastType  | 
            |
| 13 | 
                + var option: ToastOption  | 
            |
| 14 | 
                + var toastType: Toast.ToastType  | 
            |
| 15 | 15 | 
                 | 
            
| 16 | 
                + fileprivate var stackView = UIStackView(arrangedSubviews: [])  | 
            |
| 17 | 
                + fileprivate var visualView: UIVisualEffectView  | 
            |
| 16 | 18 | 
                fileprivate var label: UILabel?  | 
            
| 17 | 19 | 
                fileprivate var imageView: UIImageView?  | 
            
| 18 | 20 | 
                fileprivate var activityIndicatorView: UIActivityIndicatorView?  | 
            
                @@ -21,31 +23,60 @@ class ToastView: UIView {
               | 
            ||
| 21 | 23 | 
                fileprivate var image: UIImage?  | 
            
| 22 | 24 | 
                fileprivate var isActivity: Bool = false  | 
            
| 23 | 25 | 
                 | 
            
| 24 | 
                - fileprivate var topView: UIView?  | 
            |
| 25 | 
                - fileprivate var bottomView: UIView?  | 
            |
| 26 | 
                - fileprivate var padding = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)  | 
            |
| 27 | 
                -  | 
            |
| 26 | 
                + fileprivate var padding = UIEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)  | 
            |
| 28 | 27 | 
                 | 
            
| 29 | 28 | 
                     init(option: ToastOption, type: Toast.ToastType) {
               | 
            
| 30 | 29 | 
                self.option = option  | 
            
| 31 | 30 | 
                self.toastType = type  | 
            
| 31 | 
                + let effect = UIBlurEffect(style: .dark)  | 
            |
| 32 | 
                + self.visualView = UIVisualEffectView(effect: effect)  | 
            |
| 32 | 33 | 
                super.init(frame: CGRect.zero)  | 
            
| 33 | 
                -  | 
            |
| 34 | 34 | 
                initProperty()  | 
            
| 35 | 35 | 
                }  | 
            
| 36 | 36 | 
                 | 
            
| 37 | 
                - @available(*, unavailable, message: "Loading this view from a nib is unsupported")  | 
            |
| 38 | 
                -    public required init?(coder aDecoder: NSCoder) {
               | 
            |
| 39 | 
                -        fatalError("Loading this view from a nib is unsupported")
               | 
            |
| 37 | 
                +    required init(coder: NSCoder) {
               | 
            |
| 38 | 
                +        fatalError("init(coder:) has not been implemented")
               | 
            |
| 40 | 39 | 
                }  | 
            
| 41 | 40 | 
                 | 
            
| 42 | 41 | 
                     private func initProperty() {
               | 
            
| 43 | 
                - alpha = 0  | 
            |
| 44 | 42 | 
                layer.cornerRadius = 5  | 
            
| 45 | 
                - backgroundColor = option.backgroundColor  | 
            |
| 43 | 
                + layer.masksToBounds = true  | 
            |
| 44 | 
                +  | 
            |
| 45 | 
                + stackView.axis = .vertical  | 
            |
| 46 | 
                + stackView.alignment = .center  | 
            |
| 47 | 
                + stackView.distribution = .equalSpacing  | 
            |
| 48 | 
                + stackView.spacing = 12  | 
            |
| 49 | 
                + }  | 
            |
| 50 | 
                +  | 
            |
| 51 | 
                +    public func switchToast() {
               | 
            |
| 52 | 
                + clear()  | 
            |
| 53 | 
                + setToast()  | 
            |
| 54 | 
                + constructStackViewHierarchy()  | 
            |
| 55 | 
                + activateConstraints()  | 
            |
| 46 | 56 | 
                }  | 
            
| 47 | 57 | 
                 | 
            
| 48 | 58 | 
                     override func didMoveToWindow() {
               | 
            
| 59 | 
                + setToast()  | 
            |
| 60 | 
                +  | 
            |
| 61 | 
                + addSubview(visualView)  | 
            |
| 62 | 
                +  | 
            |
| 63 | 
                + constructStackViewHierarchy()  | 
            |
| 64 | 
                + activateConstraints()  | 
            |
| 65 | 
                + }  | 
            |
| 66 | 
                +  | 
            |
| 67 | 
                +    private func clear() {
               | 
            |
| 68 | 
                + image = nil  | 
            |
| 69 | 
                + isActivity = false  | 
            |
| 70 | 
                + text = nil  | 
            |
| 71 | 
                + let arrangedSubviews = stackView.arrangedSubviews  | 
            |
| 72 | 
                +        arrangedSubviews.forEach {
               | 
            |
| 73 | 
                + stackView.removeArrangedSubview($0)  | 
            |
| 74 | 
                + $0.removeFromSuperview()  | 
            |
| 75 | 
                + }  | 
            |
| 76 | 
                + stackView.removeFromSuperview()  | 
            |
| 77 | 
                + }  | 
            |
| 78 | 
                +  | 
            |
| 79 | 
                +    private func setToast() {
               | 
            |
| 49 | 80 | 
                         switch toastType {
               | 
            
| 50 | 81 | 
                case let .text(t):  | 
            
| 51 | 82 | 
                text = t  | 
            
                @@ -58,39 +89,53 @@ class ToastView: UIView {
               | 
            ||
| 58 | 89 | 
                text = t  | 
            
| 59 | 90 | 
                isActivity = true  | 
            
| 60 | 91 | 
                }  | 
            
| 61 | 
                -  | 
            |
| 62 | 
                - constructViewHierarchy()  | 
            |
| 63 | 
                - activateConstraints()  | 
            |
| 64 | 92 | 
                }  | 
            
| 65 | 93 | 
                }  | 
            
| 66 | 94 | 
                 | 
            
| 67 | 95 | 
                /// construct view and layout  | 
            
| 68 | 96 | 
                 fileprivate extension ToastView {
               | 
            
| 69 | 97 | 
                 | 
            
| 70 | 
                -    func constructViewHierarchy() {
               | 
            |
| 98 | 
                +    func constructStackViewHierarchy() {
               | 
            |
| 99 | 
                + addSubview(stackView)  | 
            |
| 100 | 
                +  | 
            |
| 71 | 101 | 
                         if image != nil {
               | 
            
| 72 | 102 | 
                imageView = makeImageView()  | 
            
| 73 | 
                - addSubview(imageView!)  | 
            |
| 103 | 
                +  | 
            |
| 104 | 
                + stackView.addArrangedSubview(imageView!)  | 
            |
| 74 | 105 | 
                }  | 
            
| 75 | 106 | 
                 | 
            
| 76 | 107 | 
                         if isActivity {
               | 
            
| 77 | 108 | 
                activityIndicatorView = makeActivityIndicatorView()  | 
            
| 78 | 
                - addSubview(activityIndicatorView!)  | 
            |
| 109 | 
                + stackView.addArrangedSubview(activityIndicatorView!)  | 
            |
| 79 | 110 | 
                }  | 
            
| 80 | 111 | 
                 | 
            
| 81 | 112 | 
                         if text != nil {
               | 
            
| 82 | 113 | 
                label = makeLabel()  | 
            
| 83 | 
                - addSubview(label!)  | 
            |
| 114 | 
                + stackView.addArrangedSubview(label!)  | 
            |
| 84 | 115 | 
                }  | 
            
| 85 | 116 | 
                }  | 
            
| 86 | 117 | 
                 | 
            
| 118 | 
                +  | 
            |
| 87 | 119 | 
                     func activateConstraints() {
               | 
            
| 88 | 120 | 
                activateConstraintsImage()  | 
            
| 89 | 121 | 
                activateConstraintsIndicator()  | 
            
| 90 | 122 | 
                activateConstraintsText()  | 
            
| 123 | 
                + activateConstraintsStackView()  | 
            |
| 124 | 
                + activateConstraintsVisualView()  | 
            |
| 91 | 125 | 
                activateConstraintsContentView()  | 
            
| 92 | 126 | 
                }  | 
            
| 93 | 127 | 
                 | 
            
| 128 | 
                +    func activateConstraintsStackView() {
               | 
            |
| 129 | 
                + stackView.translatesAutoresizingMaskIntoConstraints = false  | 
            |
| 130 | 
                +  | 
            |
| 131 | 
                + NSLayoutConstraint.activate([  | 
            |
| 132 | 
                + stackView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top),  | 
            |
| 133 | 
                + stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom),  | 
            |
| 134 | 
                + stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left),  | 
            |
| 135 | 
                + stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right)  | 
            |
| 136 | 
                + ])  | 
            |
| 137 | 
                + }  | 
            |
| 138 | 
                +  | 
            |
| 94 | 139 | 
                     func activateConstraintsImage() {
               | 
            
| 95 | 140 | 
                         guard let imageView = imageView else { return }
               | 
            
| 96 | 141 | 
                 | 
            
                @@ -98,25 +143,13 @@ fileprivate extension ToastView {
               | 
            ||
| 98 | 143 | 
                 | 
            
| 99 | 144 | 
                NSLayoutConstraint.activate([  | 
            
| 100 | 145 | 
                imageView.widthAnchor.constraint(equalToConstant: 50),  | 
            
| 101 | 
                - imageView.heightAnchor.constraint(equalToConstant: 50),  | 
            |
| 102 | 
                - imageView.centerXAnchor.constraint(equalTo: centerXAnchor),  | 
            |
| 103 | 
                - imageView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top)  | 
            |
| 146 | 
                + imageView.heightAnchor.constraint(equalToConstant: 50)  | 
            |
| 104 | 147 | 
                ])  | 
            
| 105 | 
                -  | 
            |
| 106 | 
                - topView = imageView  | 
            |
| 107 | 148 | 
                }  | 
            
| 108 | 149 | 
                 | 
            
| 109 | 150 | 
                     func activateConstraintsIndicator() {
               | 
            
| 110 | 151 | 
                         guard let activityIndicatorView = activityIndicatorView else { return }
               | 
            
| 111 | 152 | 
                 | 
            
| 112 | 
                - activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false  | 
            |
| 113 | 
                -  | 
            |
| 114 | 
                - NSLayoutConstraint.activate([  | 
            |
| 115 | 
                - activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor),  | 
            |
| 116 | 
                - activityIndicatorView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top)  | 
            |
| 117 | 
                - ])  | 
            |
| 118 | 
                -  | 
            |
| 119 | 
                - topView = activityIndicatorView  | 
            |
| 120 | 153 | 
                activityIndicatorView.startAnimating()  | 
            
| 121 | 154 | 
                }  | 
            
| 122 | 155 | 
                 | 
            
                @@ -128,50 +161,30 @@ fileprivate extension ToastView {
               | 
            ||
| 128 | 161 | 
                label.translatesAutoresizingMaskIntoConstraints = false  | 
            
| 129 | 162 | 
                 | 
            
| 130 | 163 | 
                NSLayoutConstraint.activate([  | 
            
| 131 | 
                - label.centerXAnchor.constraint(equalTo: centerXAnchor),  | 
            |
| 132 | 
                - widthAnchor.constraint(lessThanOrEqualToConstant: windowSize.width - 52),  | 
            |
| 133 | 
                - label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom),  | 
            |
| 134 | 
                - label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left),  | 
            |
| 135 | 
                - label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right),  | 
            |
| 136 | 
                - label.topAnchor.constraint(equalTo: topView?.bottomAnchor ?? topAnchor, constant: 6),  | 
            |
| 164 | 
                + widthAnchor.constraint(lessThanOrEqualToConstant: windowSize.width - 52)  | 
            |
| 137 | 165 | 
                ])  | 
            
| 138 | 
                -  | 
            |
| 139 | 
                -        if (text?.count ?? 0) <= 3 {
               | 
            |
| 140 | 
                -  | 
            |
| 141 | 
                -        } else {
               | 
            |
| 142 | 
                - NSLayoutConstraint.activate([  | 
            |
| 143 | 
                - ])  | 
            |
| 144 | 
                - }  | 
            |
| 145 | 
                -  | 
            |
| 146 | 
                -        if topView != nil {
               | 
            |
| 147 | 
                - NSLayoutConstraint.activate([  | 
            |
| 148 | 
                - label.widthAnchor.constraint(greaterThanOrEqualTo: heightAnchor)  | 
            |
| 149 | 
                - ])  | 
            |
| 150 | 
                - }  | 
            |
| 151 | 
                -  | 
            |
| 152 | 
                - bottomView = label  | 
            |
| 153 | 166 | 
                }  | 
            
| 154 | 167 | 
                 | 
            
| 155 | 168 | 
                     func activateConstraintsContentView() {
               | 
            
| 156 | 169 | 
                         guard let v = superview else { return }
               | 
            
| 157 | 
                - translatesAutoresizingMaskIntoConstraints = false  | 
            |
| 158 | 170 | 
                 | 
            
| 171 | 
                + translatesAutoresizingMaskIntoConstraints = false  | 
            |
| 172 | 
                +  | 
            |
| 159 | 173 | 
                NSLayoutConstraint.activate([  | 
            
| 160 | 174 | 
                centerXAnchor.constraint(equalTo: v.centerXAnchor),  | 
            
| 161 | 175 | 
                centerYAnchor.constraint(equalTo: v.centerYAnchor)  | 
            
| 162 | 176 | 
                ])  | 
            
| 177 | 
                + }  | 
            |
| 178 | 
                +  | 
            |
| 179 | 
                +    func activateConstraintsVisualView() {
               | 
            |
| 180 | 
                + visualView.translatesAutoresizingMaskIntoConstraints = false  | 
            |
| 163 | 181 | 
                 | 
            
| 164 | 
                -        if topView == nil {
               | 
            |
| 165 | 
                - NSLayoutConstraint.activate([  | 
            |
| 166 | 
                - bottomView!.topAnchor.constraint(equalTo: topAnchor, constant: padding.top)  | 
            |
| 167 | 
                - ])  | 
            |
| 168 | 
                -        } else if bottomView == nil {
               | 
            |
| 169 | 
                - NSLayoutConstraint.activate([  | 
            |
| 170 | 
                - topView!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom),  | 
            |
| 171 | 
                - topView!.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left),  | 
            |
| 172 | 
                - topView!.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right)  | 
            |
| 173 | 
                - ])  | 
            |
| 174 | 
                - }  | 
            |
| 182 | 
                + NSLayoutConstraint.activate([  | 
            |
| 183 | 
                + visualView.topAnchor.constraint(equalTo: topAnchor),  | 
            |
| 184 | 
                + visualView.leadingAnchor.constraint(equalTo: leadingAnchor),  | 
            |
| 185 | 
                + visualView.widthAnchor.constraint(equalTo: widthAnchor),  | 
            |
| 186 | 
                + visualView.heightAnchor.constraint(equalTo: heightAnchor)  | 
            |
| 187 | 
                + ])  | 
            |
| 175 | 188 | 
                }  | 
            
| 176 | 189 | 
                }  | 
            
| 177 | 190 | 
                 | 
            
                @@ -183,6 +196,7 @@ fileprivate extension ToastView {
               | 
            ||
| 183 | 196 | 
                l.font = option.font  | 
            
| 184 | 197 | 
                l.textAlignment = .center  | 
            
| 185 | 198 | 
                l.textColor = option.tintColor  | 
            
| 199 | 
                + l.sizeToFit()  | 
            |
| 186 | 200 | 
                 | 
            
| 187 | 201 | 
                return l  | 
            
| 188 | 202 | 
                }  | 
            
                @@ -195,7 +209,7 @@ fileprivate extension ToastView {
               | 
            ||
| 195 | 209 | 
                }  | 
            
| 196 | 210 | 
                 | 
            
| 197 | 211 | 
                     func makeActivityIndicatorView() -> UIActivityIndicatorView {
               | 
            
| 198 | 
                - let a = UIActivityIndicatorView(style: .white)  | 
            |
| 212 | 
                + let a = UIActivityIndicatorView(style: .whiteLarge)  | 
            |
| 199 | 213 | 
                 | 
            
| 200 | 214 | 
                return a  | 
            
| 201 | 215 | 
                }  | 
            
                @@ -40,12 +40,19 @@ public extension UIImage {
               | 
            ||
| 40 | 40 | 
                resizingMode: .stretch)  | 
            
| 41 | 41 | 
                }  | 
            
| 42 | 42 | 
                 | 
            
| 43 | 
                +        public static var blackBackground: UIImage? {
               | 
            |
| 44 | 
                + return UIImage(named: "navigation-background-black")?.resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0),  | 
            |
| 45 | 
                + resizingMode: .stretch)  | 
            |
| 46 | 
                +  | 
            |
| 47 | 
                + }  | 
            |
| 48 | 
                +  | 
            |
| 43 | 49 | 
                         public static var right: UIImage? {
               | 
            
| 44 | 50 | 
                return UIImage(named: "navigation-right")?.resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0),  | 
            
| 45 | 51 | 
                resizingMode: .stretch)  | 
            
| 46 | 52 | 
                }  | 
            
| 47 | 53 | 
                 | 
            
| 48 | 54 | 
                 | 
            
| 55 | 
                +  | 
            |
| 49 | 56 | 
                         public static var verticalPoints: UIImage? {
               | 
            
| 50 | 57 | 
                return UIImage(named: "navigation-vertical-points")?.resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0),  | 
            
| 51 | 58 | 
                resizingMode: .stretch)  | 
            
                @@ -19,11 +19,6 @@ public extension UIViewController {
               | 
            ||
| 19 | 19 | 
                navigationController?.pushViewController(vc, animated: animted)  | 
            
| 20 | 20 | 
                }  | 
            
| 21 | 21 | 
                 | 
            
| 22 | 
                -  | 
            |
| 23 | 
                -//    @objc func popViewController(animated: Bool = true) {
               | 
            |
| 24 | 
                -// navigationController?.popViewController(animated: animated)  | 
            |
| 25 | 
                -// }  | 
            |
| 26 | 
                -  | 
            |
| 27 | 22 | 
                     func popToController(_ vc: UIViewController, animated: Bool = true) {
               | 
            
| 28 | 23 | 
                navigationController?.popToViewController(vc, animated: animated)  | 
            
| 29 | 24 | 
                }  | 
            
                @@ -13,6 +13,6 @@ public protocol QRCodeScanViewDelegate: class {
               | 
            ||
| 13 | 13 | 
                func scanView(_ scanView: QRCodeScanView, didFinshWithError error: NSError?)  | 
            
| 14 | 14 | 
                }  | 
            
| 15 | 15 | 
                 | 
            
| 16 | 
                -extension QRCodeScanViewDelegate {
               | 
            |
| 16 | 
                +public extension QRCodeScanViewDelegate {
               | 
            |
| 17 | 17 | 
                     func scanView(_ scanView: QRCodeScanView, didFinshWithError error: NSError?) {}
               | 
            
| 18 | 18 | 
                }  | 
            
                @@ -8,6 +8,7 @@  | 
            ||
| 8 | 8 | 
                 | 
            
| 9 | 9 | 
                import UIKit  | 
            
| 10 | 10 | 
                import AVFoundation  | 
            
| 11 | 
                +import CoreImage  | 
            |
| 11 | 12 | 
                 | 
            
| 12 | 13 | 
                 @IBDesignable public class QRCodeScanView: UIView {
               | 
            
| 13 | 14 | 
                var qrmaskView: QRCodeMaskView?  | 
            
                @@ -115,19 +116,17 @@ import AVFoundation  | 
            ||
| 115 | 116 | 
                picker.delegate = self  | 
            
| 116 | 117 | 
                ctl.present(picker, animated: true, completion: nil)  | 
            
| 117 | 118 | 
                         } else {
               | 
            
| 118 | 
                - let alert = UIAlertView(title: "拒绝访问",  | 
            |
| 119 | 
                - message: "请在设置-隐私-相机中允许访问相册",  | 
            |
| 120 | 
                - delegate: nil,  | 
            |
| 121 | 
                - cancelButtonTitle: "确定")  | 
            |
| 122 | 
                - alert.show()  | 
            |
| 119 | 
                + let alert = UIAlertController(title: "拒绝访问", message: "请在设置-隐私-相机中允许访问相册", preferredStyle: .alert)  | 
            |
| 120 | 
                + alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))  | 
            |
| 121 | 
                + ctl.present(alert, animated: true, completion: nil)  | 
            |
| 123 | 122 | 
                }  | 
            
| 124 | 123 | 
                }  | 
            
| 125 | 124 | 
                }  | 
            
| 126 | 125 | 
                 | 
            
| 127 | 126 | 
                 extension QRCodeScanView: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
               | 
            
| 128 | 
                -    fileprivate func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
               | 
            |
| 127 | 
                +    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
               | 
            |
| 129 | 128 | 
                         picker.dismiss(animated: true) {
               | 
            
| 130 | 
                -            guard let image = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage else { return }
               | 
            |
| 129 | 
                +            guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
               | 
            |
| 131 | 130 | 
                             if let res = image.decodeQRCodeInImage() {
               | 
            
| 132 | 131 | 
                self.qrscanner?.stopScan()  | 
            
| 133 | 132 | 
                self.qrmaskView?.stopAnimation()  | 
            
                @@ -135,17 +134,17 @@ extension QRCodeScanView: UIImagePickerControllerDelegate, UINavigationControlle  | 
            ||
| 135 | 134 | 
                receivedScanResult: QRCodeScanResult(metadataType: AVMetadataObject.ObjectType.qr.rawValue,  | 
            
| 136 | 135 | 
                result: res))  | 
            
| 137 | 136 | 
                             } else {
               | 
            
| 138 | 
                - let error = NSError.init(domain: "decode qr code error",  | 
            |
| 139 | 
                - code: 101,  | 
            |
| 140 | 
                - userInfo: nil)  | 
            |
| 137 | 
                + let error = NSError(domain: "decode qr code error",  | 
            |
| 138 | 
                + code: 101,  | 
            |
| 139 | 
                + userInfo: nil)  | 
            |
| 141 | 140 | 
                self.delegate?.scanView(self,  | 
            
| 142 | 141 | 
                didFinshWithError: error)  | 
            
| 143 | 142 | 
                }  | 
            
| 144 | 143 | 
                self.indicatorView.stopAnimating()  | 
            
| 145 | 144 | 
                }  | 
            
| 146 | 145 | 
                }  | 
            
| 147 | 
                -  | 
            |
| 148 | 
                -    fileprivate func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
               | 
            |
| 146 | 
                +  | 
            |
| 147 | 
                +    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
               | 
            |
| 149 | 148 | 
                picker.dismiss(animated: true, completion: nil)  | 
            
| 150 | 149 | 
                }  | 
            
| 151 | 150 | 
                }  | 
            
                @@ -157,10 +156,9 @@ extension UIImage {
               | 
            ||
| 157 | 156 | 
                ///  | 
            
| 158 | 157 | 
                /// - Returns: 二维码信息  | 
            
| 159 | 158 | 
                     public func decodeQRCodeInImage() -> String? {
               | 
            
| 160 | 
                - let context = CIContext()  | 
            |
| 161 | 
                - let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: nil)  | 
            |
| 162 | 
                -        guard let image = CIImage(image: self) else { return nil }
               | 
            |
| 163 | 
                - let result = detector?.features(in: image)  | 
            |
| 159 | 
                + guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil),  | 
            |
| 160 | 
                +            let cgImage1 = self.cgImage else { return nil }
               | 
            |
| 161 | 
                + let result = detector.features(in: CIImage(cgImage: cgImage1), options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])  | 
            |
| 164 | 162 | 
                         guard let first = (result as? [CIQRCodeFeature])?.first else { return nil }
               | 
            
| 165 | 163 | 
                return first.messageString  | 
            
| 166 | 164 | 
                }  | 
            
                @@ -24,6 +24,23 @@  | 
            ||
| 24 | 24 | 
                <collectionViewLayout key="collectionViewLayout" id="JAB-7S-F8d" customClass="WaterfallFlowLayout" customModule="PaiaiUIKit"/>  | 
            
| 25 | 25 | 
                <cells/>  | 
            
| 26 | 26 | 
                </collectionView>  | 
            
| 27 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="6" translatesAutoresizingMaskIntoConstraints="NO" id="t0e-rE-HhA">  | 
            |
| 28 | 
                + <rect key="frame" x="0.0" y="211.5" width="375" height="264"/>  | 
            |
| 29 | 
                + <subviews>  | 
            |
| 30 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="iEw-uH-8xG">  | 
            |
| 31 | 
                + <rect key="frame" x="67.5" y="0.0" width="240" height="240"/>  | 
            |
| 32 | 
                + <constraints>  | 
            |
| 33 | 
                + <constraint firstAttribute="width" secondItem="iEw-uH-8xG" secondAttribute="height" multiplier="1:1" id="cJz-bD-POP"/>  | 
            |
| 34 | 
                + </constraints>  | 
            |
| 35 | 
                + </imageView>  | 
            |
| 36 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="邀请朋友扫描二维码加入群" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ODT-Kq-dyd">  | 
            |
| 37 | 
                + <rect key="frame" x="95.5" y="246" width="184" height="18"/>  | 
            |
| 38 | 
                + <fontDescription key="fontDescription" type="system" pointSize="15"/>  | 
            |
| 39 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 40 | 
                + <nil key="highlightedColor"/>  | 
            |
| 41 | 
                + </label>  | 
            |
| 42 | 
                + </subviews>  | 
            |
| 43 | 
                + </stackView>  | 
            |
| 27 | 44 | 
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ckt-CA-ny6">  | 
            
| 28 | 45 | 
                <rect key="frame" x="303" y="597" width="64" height="64"/>  | 
            
| 29 | 46 | 
                <constraints>  | 
            
                @@ -41,7 +58,10 @@  | 
            ||
| 41 | 58 | 
                <constraints>  | 
            
| 42 | 59 | 
                <constraint firstItem="jD2-65-6eY" firstAttribute="bottom" secondItem="Ckt-CA-ny6" secondAttribute="bottom" constant="6" id="3sN-1z-kEg"/>  | 
            
| 43 | 60 | 
                <constraint firstItem="jD2-65-6eY" firstAttribute="trailing" secondItem="SQ2-vg-KI2" secondAttribute="trailing" id="6Mx-Yn-Q9C"/>  | 
            
| 61 | 
                + <constraint firstItem="t0e-rE-HhA" firstAttribute="centerX" secondItem="jD2-65-6eY" secondAttribute="centerX" id="7Ah-BH-xjN"/>  | 
            |
| 62 | 
                + <constraint firstItem="t0e-rE-HhA" firstAttribute="centerY" secondItem="jD2-65-6eY" secondAttribute="centerY" id="B7V-VG-zvI"/>  | 
            |
| 44 | 63 | 
                <constraint firstItem="SQ2-vg-KI2" firstAttribute="top" secondItem="jD2-65-6eY" secondAttribute="top" id="SjQ-TS-6Py"/>  | 
            
| 64 | 
                + <constraint firstItem="t0e-rE-HhA" firstAttribute="width" secondItem="3WT-kq-eEc" secondAttribute="width" id="Z9w-hX-2AS"/>  | 
            |
| 45 | 65 | 
                <constraint firstItem="SQ2-vg-KI2" firstAttribute="leading" secondItem="jD2-65-6eY" secondAttribute="leading" id="jE9-N2-trU"/>  | 
            
| 46 | 66 | 
                <constraint firstItem="jD2-65-6eY" firstAttribute="trailing" secondItem="Ckt-CA-ny6" secondAttribute="trailing" constant="8" id="ory-hZ-HWM"/>  | 
            
| 47 | 67 | 
                <constraint firstAttribute="bottom" secondItem="SQ2-vg-KI2" secondAttribute="bottom" id="qMe-Om-r14"/>  | 
            
                @@ -51,12 +71,14 @@  | 
            ||
| 51 | 71 | 
                <navigationItem key="navigationItem" id="sdS-ms-7Io"/>  | 
            
| 52 | 72 | 
                <connections>  | 
            
| 53 | 73 | 
                <outlet property="collectionView" destination="SQ2-vg-KI2" id="QZZ-9l-Lg5"/>  | 
            
| 74 | 
                + <outlet property="emptyView" destination="t0e-rE-HhA" id="Ige-H6-j0I"/>  | 
            |
| 54 | 75 | 
                <outlet property="photographBtn" destination="Ckt-CA-ny6" id="nq9-32-Rhg"/>  | 
            
| 76 | 
                + <outlet property="qrImageView" destination="iEw-uH-8xG" id="smk-33-2OE"/>  | 
            |
| 55 | 77 | 
                </connections>  | 
            
| 56 | 78 | 
                </viewController>  | 
            
| 57 | 79 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="1WI-xu-c0y" sceneMemberID="firstResponder"/>  | 
            
| 58 | 80 | 
                </objects>  | 
            
| 59 | 
                - <point key="canvasLocation" x="437.5" y="63.5"/>  | 
            |
| 81 | 
                + <point key="canvasLocation" x="150" y="50"/>  | 
            |
| 60 | 82 | 
                </scene>  | 
            
| 61 | 83 | 
                </scenes>  | 
            
| 62 | 84 | 
                <resources>  | 
            
                @@ -10,95 +10,6 @@  | 
            ||
| 10 | 10 | 
                <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>  | 
            
| 11 | 11 | 
                </dependencies>  | 
            
| 12 | 12 | 
                <scenes>  | 
            
| 13 | 
                - <!--ShowGroupQRController-->  | 
            |
| 14 | 
                - <scene sceneID="XYC-ye-yVT">  | 
            |
| 15 | 
                - <objects>  | 
            |
| 16 | 
                - <viewController storyboardIdentifier="ShowGroupQRController" automaticallyAdjustsScrollViewInsets="NO" id="1xf-Gx-gQ6" userLabel="ShowGroupQRController" customClass="ShowGroupQRController" customModule="PaiAi" sceneMemberID="viewController">  | 
            |
| 17 | 
                - <view key="view" contentMode="scaleToFill" id="ZBk-gn-qqZ">  | 
            |
| 18 | 
                - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>  | 
            |
| 19 | 
                - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>  | 
            |
| 20 | 
                - <subviews>  | 
            |
| 21 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AOa-xP-S2e">  | 
            |
| 22 | 
                - <rect key="frame" x="47.5" y="132.5" width="280" height="362"/>  | 
            |
| 23 | 
                - <subviews>  | 
            |
| 24 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LsX-zm-vaZ">  | 
            |
| 25 | 
                - <rect key="frame" x="123.5" y="80" width="33" height="20"/>  | 
            |
| 26 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 27 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 28 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 29 | 
                - <nil key="highlightedColor"/>  | 
            |
| 30 | 
                - </label>  | 
            |
| 31 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="pWX-dr-m4f">  | 
            |
| 32 | 
                - <rect key="frame" x="110" y="16" width="60" height="60"/>  | 
            |
| 33 | 
                - <constraints>  | 
            |
| 34 | 
                - <constraint firstAttribute="width" secondItem="pWX-dr-m4f" secondAttribute="height" multiplier="1:1" id="Y4R-2u-6IF"/>  | 
            |
| 35 | 
                - <constraint firstAttribute="width" constant="60" id="gVZ-d2-0Zl"/>  | 
            |
| 36 | 
                - </constraints>  | 
            |
| 37 | 
                - </imageView>  | 
            |
| 38 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="默认头像" translatesAutoresizingMaskIntoConstraints="NO" id="omt-Jt-Qr4">  | 
            |
| 39 | 
                - <rect key="frame" x="40" y="114" width="200" height="200"/>  | 
            |
| 40 | 
                - <constraints>  | 
            |
| 41 | 
                - <constraint firstAttribute="width" constant="200" id="4Jq-pa-wy8"/>  | 
            |
| 42 | 
                - <constraint firstAttribute="width" secondItem="omt-Jt-Qr4" secondAttribute="height" multiplier="1:1" id="PFq-bE-xho"/>  | 
            |
| 43 | 
                - </constraints>  | 
            |
| 44 | 
                - </imageView>  | 
            |
| 45 | 
                - </subviews>  | 
            |
| 46 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 47 | 
                - <constraints>  | 
            |
| 48 | 
                - <constraint firstItem="LsX-zm-vaZ" firstAttribute="centerX" secondItem="AOa-xP-S2e" secondAttribute="centerX" id="6HE-zY-T4a"/>  | 
            |
| 49 | 
                - <constraint firstItem="LsX-zm-vaZ" firstAttribute="top" secondItem="AOa-xP-S2e" secondAttribute="top" constant="80" id="7MB-5e-afJ"/>  | 
            |
| 50 | 
                - <constraint firstAttribute="height" constant="362" id="BqC-e3-veX"/>  | 
            |
| 51 | 
                - <constraint firstItem="pWX-dr-m4f" firstAttribute="top" secondItem="AOa-xP-S2e" secondAttribute="top" constant="16" id="O0H-zl-A5Z"/>  | 
            |
| 52 | 
                - <constraint firstItem="pWX-dr-m4f" firstAttribute="centerX" secondItem="AOa-xP-S2e" secondAttribute="centerX" id="iJd-xI-avR"/>  | 
            |
| 53 | 
                - <constraint firstItem="omt-Jt-Qr4" firstAttribute="centerX" secondItem="AOa-xP-S2e" secondAttribute="centerX" id="iog-Je-bMC"/>  | 
            |
| 54 | 
                - <constraint firstItem="omt-Jt-Qr4" firstAttribute="top" secondItem="AOa-xP-S2e" secondAttribute="top" constant="114" id="onf-UA-eoS"/>  | 
            |
| 55 | 
                - <constraint firstAttribute="width" constant="280" id="smI-a8-6H9"/>  | 
            |
| 56 | 
                - </constraints>  | 
            |
| 57 | 
                - <userDefinedRuntimeAttributes>  | 
            |
| 58 | 
                - <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">  | 
            |
| 59 | 
                - <real key="value" value="0.0"/>  | 
            |
| 60 | 
                - </userDefinedRuntimeAttribute>  | 
            |
| 61 | 
                - <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 62 | 
                - <real key="value" value="0.0"/>  | 
            |
| 63 | 
                - </userDefinedRuntimeAttribute>  | 
            |
| 64 | 
                - </userDefinedRuntimeAttributes>  | 
            |
| 65 | 
                - </view>  | 
            |
| 66 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="扫描二维码加入群" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Yp-sn-LQg">  | 
            |
| 67 | 
                - <rect key="frame" x="138" y="458.5" width="99" height="15"/>  | 
            |
| 68 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 69 | 
                - <fontDescription key="fontDescription" type="system" pointSize="12"/>  | 
            |
| 70 | 
                - <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 71 | 
                - <nil key="highlightedColor"/>  | 
            |
| 72 | 
                - </label>  | 
            |
| 73 | 
                - </subviews>  | 
            |
| 74 | 
                - <gestureRecognizers/>  | 
            |
| 75 | 
                - <constraints>  | 
            |
| 76 | 
                - <constraint firstItem="3Yp-sn-LQg" firstAttribute="centerX" secondItem="omt-Jt-Qr4" secondAttribute="centerX" id="5jg-XD-1je"/>  | 
            |
| 77 | 
                - <constraint firstItem="AOa-xP-S2e" firstAttribute="centerY" secondItem="ZBk-gn-qqZ" secondAttribute="centerY" constant="-20" id="gqp-We-1FY"/>  | 
            |
| 78 | 
                - <constraint firstItem="AOa-xP-S2e" firstAttribute="centerX" secondItem="x9Y-Y7-7ge" secondAttribute="centerX" id="ou7-87-DCL"/>  | 
            |
| 79 | 
                - <constraint firstItem="3Yp-sn-LQg" firstAttribute="top" secondItem="omt-Jt-Qr4" secondAttribute="bottom" constant="12" id="vwi-7r-nUU"/>  | 
            |
| 80 | 
                - </constraints>  | 
            |
| 81 | 
                - <viewLayoutGuide key="safeArea" id="x9Y-Y7-7ge"/>  | 
            |
| 82 | 
                - <connections>  | 
            |
| 83 | 
                - <outletCollection property="gestureRecognizers" destination="qe1-cB-TmI" appends="YES" id="9kM-Mf-00B"/>  | 
            |
| 84 | 
                - </connections>  | 
            |
| 85 | 
                - </view>  | 
            |
| 86 | 
                - <connections>  | 
            |
| 87 | 
                - <outlet property="EWM" destination="omt-Jt-Qr4" id="axb-en-HEB"/>  | 
            |
| 88 | 
                - <outlet property="contentView" destination="AOa-xP-S2e" id="DWh-rw-9bu"/>  | 
            |
| 89 | 
                - <outlet property="groupImage" destination="pWX-dr-m4f" id="uLJ-jV-jfC"/>  | 
            |
| 90 | 
                - <outlet property="groupName" destination="LsX-zm-vaZ" id="Wdr-zQ-QWj"/>  | 
            |
| 91 | 
                - </connections>  | 
            |
| 92 | 
                - </viewController>  | 
            |
| 93 | 
                - <placeholder placeholderIdentifier="IBFirstResponder" id="Pp3-WT-dSC" userLabel="First Responder" sceneMemberID="firstResponder"/>  | 
            |
| 94 | 
                - <tapGestureRecognizer id="qe1-cB-TmI">  | 
            |
| 95 | 
                - <connections>  | 
            |
| 96 | 
                - <action selector="back" destination="1xf-Gx-gQ6" id="rSv-3P-jrb"/>  | 
            |
| 97 | 
                - </connections>  | 
            |
| 98 | 
                - </tapGestureRecognizer>  | 
            |
| 99 | 
                - </objects>  | 
            |
| 100 | 
                - <point key="canvasLocation" x="-232" y="2161.6191904047978"/>  | 
            |
| 101 | 
                - </scene>  | 
            |
| 102 | 13 | 
                <!--GroupDetailViewController-->  | 
            
| 103 | 14 | 
                <scene sceneID="Oa4-Yi-HJu">  | 
            
| 104 | 15 | 
                <objects>  | 
            
                @@ -107,207 +18,203 @@  | 
            ||
| 107 | 18 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>  | 
            
| 108 | 19 | 
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>  | 
            
| 109 | 20 | 
                <subviews>  | 
            
| 110 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fpL-PF-0xo" userLabel="Group Name">  | 
            |
| 111 | 
                - <rect key="frame" x="0.0" y="25" width="375" height="45"/>  | 
            |
| 21 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="eF5-Vm-thF">  | 
            |
| 22 | 
                + <rect key="frame" x="0.0" y="20" width="375" height="225"/>  | 
            |
| 112 | 23 | 
                <subviews>  | 
            
| 113 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NME-fp-tEb">  | 
            |
| 114 | 
                - <rect key="frame" x="12" y="12.5" width="49" height="20"/>  | 
            |
| 115 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 116 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 117 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 118 | 
                - <nil key="highlightedColor"/>  | 
            |
| 119 | 
                - </label>  | 
            |
| 120 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1X6-D5-hkj">  | 
            |
| 121 | 
                - <rect key="frame" x="329" y="22.5" width="0.0" height="0.0"/>  | 
            |
| 122 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 123 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 124 | 
                - <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 125 | 
                - <nil key="highlightedColor"/>  | 
            |
| 126 | 
                - </label>  | 
            |
| 127 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="7Hg-xN-Smd">  | 
            |
| 128 | 
                - <rect key="frame" x="339" y="4.5" width="24" height="36"/>  | 
            |
| 129 | 
                - </imageView>  | 
            |
| 130 | 
                - </subviews>  | 
            |
| 131 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 132 | 
                - <gestureRecognizers/>  | 
            |
| 133 | 
                - <constraints>  | 
            |
| 134 | 
                - <constraint firstItem="7Hg-xN-Smd" firstAttribute="centerY" secondItem="fpL-PF-0xo" secondAttribute="centerY" id="Rjv-h5-Wtq"/>  | 
            |
| 135 | 
                - <constraint firstAttribute="height" constant="45" id="UPg-bK-pto"/>  | 
            |
| 136 | 
                - <constraint firstItem="NME-fp-tEb" firstAttribute="centerY" secondItem="fpL-PF-0xo" secondAttribute="centerY" id="X0F-x5-Iql"/>  | 
            |
| 137 | 
                - <constraint firstItem="NME-fp-tEb" firstAttribute="leading" secondItem="fpL-PF-0xo" secondAttribute="leading" constant="12" id="Znr-w6-kFQ"/>  | 
            |
| 138 | 
                - <constraint firstItem="7Hg-xN-Smd" firstAttribute="leading" secondItem="1X6-D5-hkj" secondAttribute="trailing" constant="10" id="qjJ-vN-hzP"/>  | 
            |
| 139 | 
                - <constraint firstAttribute="trailing" secondItem="7Hg-xN-Smd" secondAttribute="trailing" constant="12" id="tEJ-5a-H97"/>  | 
            |
| 140 | 
                - <constraint firstItem="1X6-D5-hkj" firstAttribute="centerY" secondItem="fpL-PF-0xo" secondAttribute="centerY" id="v6h-VQ-qa8"/>  | 
            |
| 141 | 
                - </constraints>  | 
            |
| 142 | 
                - <connections>  | 
            |
| 143 | 
                - <outletCollection property="gestureRecognizers" destination="QhO-Be-7C1" appends="YES" id="9lj-Za-c71"/>  | 
            |
| 144 | 
                - </connections>  | 
            |
| 145 | 
                - </view>  | 
            |
| 146 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pMy-uJ-dNy" userLabel="Group Member">  | 
            |
| 147 | 
                - <rect key="frame" x="0.0" y="70" width="375" height="90"/>  | 
            |
| 148 | 
                - <subviews>  | 
            |
| 149 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wyR-pX-r7o">  | 
            |
| 24 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3DP-6l-tA7" userLabel="Group Name">  | 
            |
| 150 | 25 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="45"/>  | 
            
| 151 | 26 | 
                <subviews>  | 
            
| 152 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群成员" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NxF-Pa-Uwm">  | 
            |
| 153 | 
                - <rect key="frame" x="12" y="12.5" width="49" height="20"/>  | 
            |
| 27 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EgZ-Rf-o71">  | 
            |
| 28 | 
                + <rect key="frame" x="12" y="13" width="49" height="19.5"/>  | 
            |
| 154 | 29 | 
                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            
| 155 | 30 | 
                <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            
| 156 | 31 | 
                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 157 | 32 | 
                <nil key="highlightedColor"/>  | 
            
| 158 | 33 | 
                </label>  | 
            
| 159 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="10人" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AxF-rT-r4a">  | 
            |
| 160 | 
                - <rect key="frame" x="299" y="12.5" width="34" height="20"/>  | 
            |
| 34 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Sv7-52-SPp">  | 
            |
| 35 | 
                + <rect key="frame" x="329" y="22.5" width="0.0" height="0.0"/>  | 
            |
| 161 | 36 | 
                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            
| 162 | 37 | 
                <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            
| 163 | 38 | 
                <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 164 | 39 | 
                <nil key="highlightedColor"/>  | 
            
| 165 | 40 | 
                </label>  | 
            
| 166 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="deA-EV-s1P">  | 
            |
| 41 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="i8n-NV-HOx">  | 
            |
| 167 | 42 | 
                <rect key="frame" x="339" y="4.5" width="24" height="36"/>  | 
            
| 168 | 43 | 
                </imageView>  | 
            
| 169 | 44 | 
                </subviews>  | 
            
| 170 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 45 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 46 | 
                + <gestureRecognizers/>  | 
            |
| 171 | 47 | 
                <constraints>  | 
            
| 172 | 
                - <constraint firstAttribute="trailing" secondItem="deA-EV-s1P" secondAttribute="trailing" constant="12" id="99G-fm-NjO"/>  | 
            |
| 173 | 
                - <constraint firstItem="deA-EV-s1P" firstAttribute="leading" secondItem="AxF-rT-r4a" secondAttribute="trailing" constant="6" id="NoO-0x-719"/>  | 
            |
| 174 | 
                - <constraint firstAttribute="height" constant="45" id="OmQ-ue-3uc"/>  | 
            |
| 175 | 
                - <constraint firstItem="NxF-Pa-Uwm" firstAttribute="leading" secondItem="wyR-pX-r7o" secondAttribute="leading" constant="12" id="RxE-Ec-vzI"/>  | 
            |
| 176 | 
                - <constraint firstItem="NxF-Pa-Uwm" firstAttribute="centerY" secondItem="wyR-pX-r7o" secondAttribute="centerY" id="jRi-u6-4du"/>  | 
            |
| 177 | 
                - <constraint firstItem="deA-EV-s1P" firstAttribute="centerY" secondItem="wyR-pX-r7o" secondAttribute="centerY" id="lcj-B2-CSF"/>  | 
            |
| 178 | 
                - <constraint firstItem="AxF-rT-r4a" firstAttribute="centerY" secondItem="wyR-pX-r7o" secondAttribute="centerY" id="s7D-rf-GV6"/>  | 
            |
| 48 | 
                + <constraint firstAttribute="trailing" secondItem="i8n-NV-HOx" secondAttribute="trailing" constant="12" id="0Ii-HJ-nJm"/>  | 
            |
| 49 | 
                + <constraint firstAttribute="height" constant="45" id="20x-CX-Soa"/>  | 
            |
| 50 | 
                + <constraint firstItem="EgZ-Rf-o71" firstAttribute="centerY" secondItem="3DP-6l-tA7" secondAttribute="centerY" id="EXH-C5-I5R"/>  | 
            |
| 51 | 
                + <constraint firstItem="i8n-NV-HOx" firstAttribute="centerY" secondItem="3DP-6l-tA7" secondAttribute="centerY" id="F9Q-ge-Na8"/>  | 
            |
| 52 | 
                + <constraint firstItem="EgZ-Rf-o71" firstAttribute="leading" secondItem="3DP-6l-tA7" secondAttribute="leading" constant="12" id="LCj-o7-LJQ"/>  | 
            |
| 53 | 
                + <constraint firstItem="i8n-NV-HOx" firstAttribute="leading" secondItem="Sv7-52-SPp" secondAttribute="trailing" constant="10" id="Oq2-SO-ogB"/>  | 
            |
| 54 | 
                + <constraint firstItem="Sv7-52-SPp" firstAttribute="centerY" secondItem="3DP-6l-tA7" secondAttribute="centerY" id="hML-m6-vCa"/>  | 
            |
| 179 | 55 | 
                </constraints>  | 
            
| 56 | 
                + <connections>  | 
            |
| 57 | 
                + <outletCollection property="gestureRecognizers" destination="QhO-Be-7C1" appends="YES" id="Z5i-Sr-TNc"/>  | 
            |
| 58 | 
                + </connections>  | 
            |
| 180 | 59 | 
                </view>  | 
            
| 181 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PEf-pV-jyM" customClass="GroupDetailMemeberView" customModule="Paiai_iOS" customModuleProvider="target">  | 
            |
| 182 | 
                - <rect key="frame" x="0.0" y="45" width="375" height="45"/>  | 
            |
| 183 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 60 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NxF-oL-8bw" userLabel="Group Member">  | 
            |
| 61 | 
                + <rect key="frame" x="0.0" y="45" width="375" height="90"/>  | 
            |
| 62 | 
                + <subviews>  | 
            |
| 63 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jUc-1D-3th">  | 
            |
| 64 | 
                + <rect key="frame" x="0.0" y="0.0" width="375" height="45"/>  | 
            |
| 65 | 
                + <subviews>  | 
            |
| 66 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群成员" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tpV-44-bE1">  | 
            |
| 67 | 
                + <rect key="frame" x="12" y="13" width="49" height="19.5"/>  | 
            |
| 68 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 69 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 70 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 71 | 
                + <nil key="highlightedColor"/>  | 
            |
| 72 | 
                + </label>  | 
            |
| 73 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="10人" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HZE-FN-DyQ">  | 
            |
| 74 | 
                + <rect key="frame" x="299.5" y="13" width="33.5" height="19.5"/>  | 
            |
| 75 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 76 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 77 | 
                + <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 78 | 
                + <nil key="highlightedColor"/>  | 
            |
| 79 | 
                + </label>  | 
            |
| 80 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="0KU-Hj-GCy">  | 
            |
| 81 | 
                + <rect key="frame" x="339" y="4.5" width="24" height="36"/>  | 
            |
| 82 | 
                + </imageView>  | 
            |
| 83 | 
                + </subviews>  | 
            |
| 84 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 85 | 
                + <constraints>  | 
            |
| 86 | 
                + <constraint firstAttribute="trailing" secondItem="0KU-Hj-GCy" secondAttribute="trailing" constant="12" id="8S3-J3-Yyh"/>  | 
            |
| 87 | 
                + <constraint firstItem="tpV-44-bE1" firstAttribute="centerY" secondItem="jUc-1D-3th" secondAttribute="centerY" id="9WO-P7-gOL"/>  | 
            |
| 88 | 
                + <constraint firstItem="0KU-Hj-GCy" firstAttribute="centerY" secondItem="jUc-1D-3th" secondAttribute="centerY" id="Bef-yS-WWO"/>  | 
            |
| 89 | 
                + <constraint firstItem="0KU-Hj-GCy" firstAttribute="leading" secondItem="HZE-FN-DyQ" secondAttribute="trailing" constant="6" id="Ro6-4G-yFP"/>  | 
            |
| 90 | 
                + <constraint firstAttribute="height" constant="45" id="Rwb-3W-tuU"/>  | 
            |
| 91 | 
                + <constraint firstItem="tpV-44-bE1" firstAttribute="leading" secondItem="jUc-1D-3th" secondAttribute="leading" constant="12" id="mgZ-37-wOQ"/>  | 
            |
| 92 | 
                + <constraint firstItem="HZE-FN-DyQ" firstAttribute="centerY" secondItem="jUc-1D-3th" secondAttribute="centerY" id="x7o-Ie-5Wd"/>  | 
            |
| 93 | 
                + </constraints>  | 
            |
| 94 | 
                + </view>  | 
            |
| 95 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gAe-sP-K7J" customClass="GroupDetailMemeberView" customModule="Paiai_iOS" customModuleProvider="target">  | 
            |
| 96 | 
                + <rect key="frame" x="0.0" y="45" width="375" height="45"/>  | 
            |
| 97 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 98 | 
                + <constraints>  | 
            |
| 99 | 
                + <constraint firstAttribute="height" constant="45" id="jsl-Zu-k11"/>  | 
            |
| 100 | 
                + </constraints>  | 
            |
| 101 | 
                + </view>  | 
            |
| 102 | 
                + </subviews>  | 
            |
| 103 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 184 | 104 | 
                <constraints>  | 
            
| 185 | 
                - <constraint firstAttribute="height" constant="45" id="zVY-I6-46P"/>  | 
            |
| 105 | 
                + <constraint firstItem="gAe-sP-K7J" firstAttribute="top" secondItem="jUc-1D-3th" secondAttribute="bottom" id="5ck-Rv-4zf"/>  | 
            |
| 106 | 
                + <constraint firstAttribute="trailing" secondItem="gAe-sP-K7J" secondAttribute="trailing" id="7bc-CV-rAR"/>  | 
            |
| 107 | 
                + <constraint firstItem="gAe-sP-K7J" firstAttribute="leading" secondItem="NxF-oL-8bw" secondAttribute="leading" id="Cbr-kU-40o"/>  | 
            |
| 108 | 
                + <constraint firstAttribute="height" constant="90" id="TIa-pW-jwd"/>  | 
            |
| 109 | 
                + <constraint firstItem="jUc-1D-3th" firstAttribute="top" secondItem="NxF-oL-8bw" secondAttribute="top" id="bzE-8j-npG"/>  | 
            |
| 110 | 
                + <constraint firstAttribute="trailing" secondItem="jUc-1D-3th" secondAttribute="trailing" id="qdM-oh-oG0"/>  | 
            |
| 111 | 
                + <constraint firstItem="jUc-1D-3th" firstAttribute="leading" secondItem="NxF-oL-8bw" secondAttribute="leading" id="yWi-UY-9VM"/>  | 
            |
| 186 | 112 | 
                </constraints>  | 
            
| 113 | 
                + <connections>  | 
            |
| 114 | 
                + <outletCollection property="gestureRecognizers" destination="PAc-yU-TO1" appends="YES" id="Cz9-0C-Lgl"/>  | 
            |
| 115 | 
                + </connections>  | 
            |
| 187 | 116 | 
                </view>  | 
            
| 188 | 
                - </subviews>  | 
            |
| 189 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 190 | 
                - <constraints>  | 
            |
| 191 | 
                - <constraint firstAttribute="trailing" secondItem="PEf-pV-jyM" secondAttribute="trailing" id="FQu-9X-fNW"/>  | 
            |
| 192 | 
                - <constraint firstAttribute="trailing" secondItem="wyR-pX-r7o" secondAttribute="trailing" id="Rhr-fu-vjC"/>  | 
            |
| 193 | 
                - <constraint firstItem="PEf-pV-jyM" firstAttribute="top" secondItem="wyR-pX-r7o" secondAttribute="bottom" id="T2J-6h-hMy"/>  | 
            |
| 194 | 
                - <constraint firstAttribute="height" constant="90" id="ksr-Ie-zrU"/>  | 
            |
| 195 | 
                - <constraint firstItem="wyR-pX-r7o" firstAttribute="top" secondItem="pMy-uJ-dNy" secondAttribute="top" id="sND-x0-GOF"/>  | 
            |
| 196 | 
                - <constraint firstItem="wyR-pX-r7o" firstAttribute="leading" secondItem="pMy-uJ-dNy" secondAttribute="leading" id="wJT-Tt-evG"/>  | 
            |
| 197 | 
                - <constraint firstItem="PEf-pV-jyM" firstAttribute="leading" secondItem="pMy-uJ-dNy" secondAttribute="leading" id="xfn-6R-s6e"/>  | 
            |
| 198 | 
                - </constraints>  | 
            |
| 199 | 
                - <connections>  | 
            |
| 200 | 
                - <outletCollection property="gestureRecognizers" destination="PAc-yU-TO1" appends="YES" id="HrQ-Km-0rQ"/>  | 
            |
| 201 | 
                - </connections>  | 
            |
| 202 | 
                - </view>  | 
            |
| 203 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rPs-2T-yj8" userLabel="Group QR">  | 
            |
| 204 | 
                - <rect key="frame" x="0.0" y="160" width="375" height="45"/>  | 
            |
| 205 | 
                - <subviews>  | 
            |
| 206 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群二维码" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZfP-6I-3jY">  | 
            |
| 207 | 
                - <rect key="frame" x="12" y="12.5" width="66" height="20"/>  | 
            |
| 208 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 209 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 210 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 211 | 
                - <nil key="highlightedColor"/>  | 
            |
| 212 | 
                - </label>  | 
            |
| 213 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="Uws-7i-Qzj">  | 
            |
| 214 | 
                - <rect key="frame" x="339" y="4.5" width="24" height="36"/>  | 
            |
| 215 | 
                - </imageView>  | 
            |
| 216 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-QR" translatesAutoresizingMaskIntoConstraints="NO" id="ZNi-wI-pOY">  | 
            |
| 217 | 
                - <rect key="frame" x="305" y="10.5" width="24" height="24"/>  | 
            |
| 117 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Mdq-nz-jXt" userLabel="Group QR">  | 
            |
| 118 | 
                + <rect key="frame" x="0.0" y="135" width="375" height="45"/>  | 
            |
| 119 | 
                + <subviews>  | 
            |
| 120 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群二维码" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lfa-Ov-NXG">  | 
            |
| 121 | 
                + <rect key="frame" x="12" y="13" width="65.5" height="19.5"/>  | 
            |
| 122 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 123 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 124 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 125 | 
                + <nil key="highlightedColor"/>  | 
            |
| 126 | 
                + </label>  | 
            |
| 127 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="IXn-b1-K62">  | 
            |
| 128 | 
                + <rect key="frame" x="339" y="4.5" width="24" height="36"/>  | 
            |
| 129 | 
                + </imageView>  | 
            |
| 130 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-QR" translatesAutoresizingMaskIntoConstraints="NO" id="NsS-cG-FY5">  | 
            |
| 131 | 
                + <rect key="frame" x="305" y="10.5" width="24" height="24"/>  | 
            |
| 132 | 
                + <constraints>  | 
            |
| 133 | 
                + <constraint firstAttribute="width" constant="24" id="YQf-I7-DB5"/>  | 
            |
| 134 | 
                + <constraint firstAttribute="height" constant="24" id="pu8-YH-Lmv"/>  | 
            |
| 135 | 
                + </constraints>  | 
            |
| 136 | 
                + </imageView>  | 
            |
| 137 | 
                + </subviews>  | 
            |
| 138 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 218 | 139 | 
                <constraints>  | 
            
| 219 | 
                - <constraint firstAttribute="width" constant="24" id="DzA-gm-u2E"/>  | 
            |
| 220 | 
                - <constraint firstAttribute="height" constant="24" id="kJ3-8V-wGS"/>  | 
            |
| 140 | 
                + <constraint firstItem="lfa-Ov-NXG" firstAttribute="centerY" secondItem="Mdq-nz-jXt" secondAttribute="centerY" id="CdN-dy-MDB"/>  | 
            |
| 141 | 
                + <constraint firstItem="lfa-Ov-NXG" firstAttribute="leading" secondItem="Mdq-nz-jXt" secondAttribute="leading" constant="12" id="Lf1-UA-hHs"/>  | 
            |
| 142 | 
                + <constraint firstItem="IXn-b1-K62" firstAttribute="centerY" secondItem="Mdq-nz-jXt" secondAttribute="centerY" id="NFS-0b-g1u"/>  | 
            |
| 143 | 
                + <constraint firstAttribute="trailing" secondItem="IXn-b1-K62" secondAttribute="trailing" constant="12" id="NcT-bO-bju"/>  | 
            |
| 144 | 
                + <constraint firstItem="NsS-cG-FY5" firstAttribute="centerY" secondItem="Mdq-nz-jXt" secondAttribute="centerY" id="OpY-xK-6h8"/>  | 
            |
| 145 | 
                + <constraint firstItem="IXn-b1-K62" firstAttribute="leading" secondItem="NsS-cG-FY5" secondAttribute="trailing" constant="10" id="S3s-U9-eAG"/>  | 
            |
| 146 | 
                + <constraint firstAttribute="height" constant="45" id="d1j-ge-Nas"/>  | 
            |
| 221 | 147 | 
                </constraints>  | 
            
| 222 | 
                - </imageView>  | 
            |
| 223 | 
                - </subviews>  | 
            |
| 224 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 225 | 
                - <constraints>  | 
            |
| 226 | 
                - <constraint firstItem="Uws-7i-Qzj" firstAttribute="centerY" secondItem="rPs-2T-yj8" secondAttribute="centerY" id="2wQ-j8-t3z"/>  | 
            |
| 227 | 
                - <constraint firstAttribute="trailing" secondItem="Uws-7i-Qzj" secondAttribute="trailing" constant="12" id="7qb-cu-8iE"/>  | 
            |
| 228 | 
                - <constraint firstItem="ZfP-6I-3jY" firstAttribute="leading" secondItem="rPs-2T-yj8" secondAttribute="leading" constant="12" id="9xA-HF-Mlj"/>  | 
            |
| 229 | 
                - <constraint firstItem="ZfP-6I-3jY" firstAttribute="centerY" secondItem="rPs-2T-yj8" secondAttribute="centerY" id="GAH-Ls-Ixp"/>  | 
            |
| 230 | 
                - <constraint firstItem="ZNi-wI-pOY" firstAttribute="centerY" secondItem="rPs-2T-yj8" secondAttribute="centerY" id="Mst-vH-6Op"/>  | 
            |
| 231 | 
                - <constraint firstItem="Uws-7i-Qzj" firstAttribute="leading" secondItem="ZNi-wI-pOY" secondAttribute="trailing" constant="10" id="eQT-7f-sku"/>  | 
            |
| 232 | 
                - <constraint firstAttribute="height" constant="45" id="ypH-Mg-3iM"/>  | 
            |
| 233 | 
                - </constraints>  | 
            |
| 234 | 
                - <connections>  | 
            |
| 235 | 
                - <outletCollection property="gestureRecognizers" destination="CLv-er-MwX" appends="YES" id="6Fw-lQ-Aqq"/>  | 
            |
| 236 | 
                - </connections>  | 
            |
| 237 | 
                - </view>  | 
            |
| 238 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Pb3-YX-nuZ" userLabel="Group Lock">  | 
            |
| 239 | 
                - <rect key="frame" x="0.0" y="205" width="375" height="45"/>  | 
            |
| 240 | 
                - <subviews>  | 
            |
| 241 | 
                - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="t9Z-kG-PPs">  | 
            |
| 242 | 
                - <rect key="frame" x="314" y="7" width="51" height="31"/>  | 
            |
| 243 | 
                - <color key="onTintColor" red="0.97647058819999999" green="0.34901960780000002" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 244 | 148 | 
                <connections>  | 
            
| 245 | 
                - <action selector="changeSwitch" destination="s9X-RR-Rat" eventType="valueChanged" id="vRG-9q-Y4n"/>  | 
            |
| 149 | 
                + <outletCollection property="gestureRecognizers" destination="CLv-er-MwX" appends="YES" id="YAD-Z4-Zqm"/>  | 
            |
| 246 | 150 | 
                </connections>  | 
            
| 247 | 
                - </switch>  | 
            |
| 248 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="群锁定" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pGa-DR-SDU">  | 
            |
| 249 | 
                - <rect key="frame" x="12" y="12.5" width="49" height="20"/>  | 
            |
| 250 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 251 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 252 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 253 | 
                - <nil key="highlightedColor"/>  | 
            |
| 254 | 
                - </label>  | 
            |
| 255 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群未锁定,可以邀请新成员加入" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="niR-rQ-aFl">  | 
            |
| 256 | 
                - <rect key="frame" x="77" y="15.5" width="221" height="17"/>  | 
            |
| 257 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 258 | 
                - <fontDescription key="fontDescription" type="system" pointSize="14"/>  | 
            |
| 259 | 
                - <color key="textColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 260 | 
                - <nil key="highlightedColor"/>  | 
            |
| 261 | 
                - </label>  | 
            |
| 151 | 
                + </view>  | 
            |
| 152 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="euC-CX-gvx" userLabel="Group Lock">  | 
            |
| 153 | 
                + <rect key="frame" x="0.0" y="180" width="375" height="45"/>  | 
            |
| 154 | 
                + <subviews>  | 
            |
| 155 | 
                + <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BHD-pt-RTg">  | 
            |
| 156 | 
                + <rect key="frame" x="314" y="7" width="51" height="31"/>  | 
            |
| 157 | 
                + <color key="onTintColor" red="0.97647058819999999" green="0.34901960780000002" blue="0.50196078430000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 158 | 
                + <connections>  | 
            |
| 159 | 
                + <action selector="changeSwitch" destination="s9X-RR-Rat" eventType="valueChanged" id="hmQ-IO-RLr"/>  | 
            |
| 160 | 
                + </connections>  | 
            |
| 161 | 
                + </switch>  | 
            |
| 162 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="群锁定" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="W2B-lN-jKI">  | 
            |
| 163 | 
                + <rect key="frame" x="12" y="13" width="49" height="19.5"/>  | 
            |
| 164 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 165 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 166 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 167 | 
                + <nil key="highlightedColor"/>  | 
            |
| 168 | 
                + </label>  | 
            |
| 169 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群未锁定,可以邀请新成员加入" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="3Yr-Gn-GlA">  | 
            |
| 170 | 
                + <rect key="frame" x="77" y="15.5" width="221" height="17"/>  | 
            |
| 171 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            |
| 172 | 
                + <fontDescription key="fontDescription" type="system" pointSize="14"/>  | 
            |
| 173 | 
                + <color key="textColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 174 | 
                + <nil key="highlightedColor"/>  | 
            |
| 175 | 
                + </label>  | 
            |
| 176 | 
                + </subviews>  | 
            |
| 177 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 178 | 
                + <constraints>  | 
            |
| 179 | 
                + <constraint firstAttribute="height" constant="45" id="4xj-Zd-riE"/>  | 
            |
| 180 | 
                + <constraint firstItem="BHD-pt-RTg" firstAttribute="leading" secondItem="3Yr-Gn-GlA" secondAttribute="trailing" constant="16" id="M98-BM-2lz"/>  | 
            |
| 181 | 
                + <constraint firstItem="3Yr-Gn-GlA" firstAttribute="bottom" secondItem="W2B-lN-jKI" secondAttribute="bottom" id="MMH-bL-Dek"/>  | 
            |
| 182 | 
                + <constraint firstItem="W2B-lN-jKI" firstAttribute="leading" secondItem="euC-CX-gvx" secondAttribute="leading" constant="12" id="Xwa-8I-bNK"/>  | 
            |
| 183 | 
                + <constraint firstItem="3Yr-Gn-GlA" firstAttribute="leading" secondItem="W2B-lN-jKI" secondAttribute="trailing" constant="16" id="ZVy-6a-GFz"/>  | 
            |
| 184 | 
                + <constraint firstAttribute="trailing" secondItem="BHD-pt-RTg" secondAttribute="trailing" constant="12" id="fUg-Vn-LXT"/>  | 
            |
| 185 | 
                + <constraint firstItem="BHD-pt-RTg" firstAttribute="centerY" secondItem="euC-CX-gvx" secondAttribute="centerY" id="rJa-xe-Kqo"/>  | 
            |
| 186 | 
                + <constraint firstItem="W2B-lN-jKI" firstAttribute="centerY" secondItem="euC-CX-gvx" secondAttribute="centerY" id="srY-5W-aCJ"/>  | 
            |
| 187 | 
                + </constraints>  | 
            |
| 188 | 
                + </view>  | 
            |
| 262 | 189 | 
                </subviews>  | 
            
| 263 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 264 | 
                - <constraints>  | 
            |
| 265 | 
                - <constraint firstAttribute="trailing" secondItem="t9Z-kG-PPs" secondAttribute="trailing" constant="12" id="KkU-tC-Egu"/>  | 
            |
| 266 | 
                - <constraint firstAttribute="height" constant="45" id="SJk-Ib-saK"/>  | 
            |
| 267 | 
                - <constraint firstItem="t9Z-kG-PPs" firstAttribute="leading" secondItem="niR-rQ-aFl" secondAttribute="trailing" constant="16" id="fz2-LG-fUc"/>  | 
            |
| 268 | 
                - <constraint firstItem="pGa-DR-SDU" firstAttribute="centerY" secondItem="Pb3-YX-nuZ" secondAttribute="centerY" id="g0e-A6-o5n"/>  | 
            |
| 269 | 
                - <constraint firstItem="pGa-DR-SDU" firstAttribute="leading" secondItem="Pb3-YX-nuZ" secondAttribute="leading" constant="12" id="l6i-0S-OgW"/>  | 
            |
| 270 | 
                - <constraint firstItem="t9Z-kG-PPs" firstAttribute="centerY" secondItem="Pb3-YX-nuZ" secondAttribute="centerY" id="oaN-d4-VQp"/>  | 
            |
| 271 | 
                - <constraint firstItem="niR-rQ-aFl" firstAttribute="leading" secondItem="pGa-DR-SDU" secondAttribute="trailing" constant="16" id="u9L-r3-u2w"/>  | 
            |
| 272 | 
                - <constraint firstItem="niR-rQ-aFl" firstAttribute="bottom" secondItem="pGa-DR-SDU" secondAttribute="bottom" id="yNV-6l-bfB"/>  | 
            |
| 273 | 
                - </constraints>  | 
            |
| 274 | 
                - </view>  | 
            |
| 190 | 
                + </stackView>  | 
            |
| 275 | 191 | 
                </subviews>  | 
            
| 276 | 192 | 
                <color key="backgroundColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 277 | 193 | 
                <constraints>  | 
            
| 278 | 
                - <constraint firstItem="pMy-uJ-dNy" firstAttribute="leading" secondItem="cIo-kp-fSE" secondAttribute="leading" id="DJT-ec-BYi"/>  | 
            |
| 279 | 
                - <constraint firstItem="cIo-kp-fSE" firstAttribute="trailing" secondItem="Pb3-YX-nuZ" secondAttribute="trailing" id="GHr-gH-44j"/>  | 
            |
| 280 | 
                - <constraint firstItem="rPs-2T-yj8" firstAttribute="top" secondItem="pMy-uJ-dNy" secondAttribute="bottom" id="PC0-el-XOL"/>  | 
            |
| 281 | 
                - <constraint firstItem="cIo-kp-fSE" firstAttribute="trailing" secondItem="rPs-2T-yj8" secondAttribute="trailing" id="SBF-Gf-sea"/>  | 
            |
| 282 | 
                - <constraint firstItem="cIo-kp-fSE" firstAttribute="trailing" secondItem="fpL-PF-0xo" secondAttribute="trailing" id="dKZ-bN-aud"/>  | 
            |
| 283 | 
                - <constraint firstItem="fpL-PF-0xo" firstAttribute="leading" secondItem="cIo-kp-fSE" secondAttribute="leading" id="dvc-Qp-fCK"/>  | 
            |
| 284 | 
                - <constraint firstItem="rPs-2T-yj8" firstAttribute="leading" secondItem="cIo-kp-fSE" secondAttribute="leading" id="exJ-yM-58B"/>  | 
            |
| 285 | 
                - <constraint firstItem="pMy-uJ-dNy" firstAttribute="top" secondItem="fpL-PF-0xo" secondAttribute="bottom" id="iBX-Qu-4Rh"/>  | 
            |
| 286 | 
                - <constraint firstItem="Pb3-YX-nuZ" firstAttribute="leading" secondItem="cIo-kp-fSE" secondAttribute="leading" id="lm3-hT-PcR"/>  | 
            |
| 287 | 
                - <constraint firstItem="cIo-kp-fSE" firstAttribute="trailing" secondItem="pMy-uJ-dNy" secondAttribute="trailing" id="mOe-DU-Rdn"/>  | 
            |
| 288 | 
                - <constraint firstItem="Pb3-YX-nuZ" firstAttribute="top" secondItem="rPs-2T-yj8" secondAttribute="bottom" id="ow5-8x-3xA"/>  | 
            |
| 289 | 
                - <constraint firstItem="fpL-PF-0xo" firstAttribute="top" secondItem="cIo-kp-fSE" secondAttribute="top" constant="5" id="wQP-uP-4dl"/>  | 
            |
| 194 | 
                + <constraint firstItem="cIo-kp-fSE" firstAttribute="trailing" secondItem="eF5-Vm-thF" secondAttribute="trailing" id="JNg-sX-8Cu"/>  | 
            |
| 195 | 
                + <constraint firstItem="eF5-Vm-thF" firstAttribute="top" secondItem="cIo-kp-fSE" secondAttribute="top" id="d34-oy-pVa"/>  | 
            |
| 196 | 
                + <constraint firstItem="eF5-Vm-thF" firstAttribute="leading" secondItem="cIo-kp-fSE" secondAttribute="leading" id="osC-NS-iQM"/>  | 
            |
| 290 | 197 | 
                </constraints>  | 
            
| 291 | 198 | 
                <viewLayoutGuide key="safeArea" id="cIo-kp-fSE"/>  | 
            
| 292 | 199 | 
                </view>  | 
            
| 293 | 200 | 
                <navigationItem key="navigationItem" id="Cjc-V8-n6M"/>  | 
            
| 294 | 201 | 
                <connections>  | 
            
| 295 | 
                - <outlet property="groupLockSwitch" destination="t9Z-kG-PPs" id="mJz-yT-bcT"/>  | 
            |
| 296 | 
                - <outlet property="groupLockTip" destination="niR-rQ-aFl" id="AX6-6k-zux"/>  | 
            |
| 297 | 
                - <outlet property="groupMemberCountLabel" destination="AxF-rT-r4a" id="eOC-vz-TTc"/>  | 
            |
| 298 | 
                - <outlet property="groupMemeberView" destination="PEf-pV-jyM" id="Cqs-Fq-QzC"/>  | 
            |
| 299 | 
                - <outlet property="groupNameLabel" destination="1X6-D5-hkj" id="neB-7y-IOQ"/>  | 
            |
| 202 | 
                + <outlet property="groupLockSwitch" destination="BHD-pt-RTg" id="3Ip-yz-qDn"/>  | 
            |
| 203 | 
                + <outlet property="groupLockTip" destination="3Yr-Gn-GlA" id="vZj-kd-JUR"/>  | 
            |
| 204 | 
                + <outlet property="groupMemberCountLabel" destination="HZE-FN-DyQ" id="A7o-Ij-sbh"/>  | 
            |
| 205 | 
                + <outlet property="groupMemeberView" destination="gAe-sP-K7J" id="BgX-En-nx3"/>  | 
            |
| 206 | 
                + <outlet property="groupNameLabel" destination="Sv7-52-SPp" id="Q1p-sJ-2da"/>  | 
            |
| 300 | 207 | 
                </connections>  | 
            
| 301 | 208 | 
                </viewController>  | 
            
| 302 | 209 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="3Gk-LZ-t7S" sceneMemberID="firstResponder"/>  | 
            
| 303 | 210 | 
                <tapGestureRecognizer id="QhO-Be-7C1" userLabel="GroupNameGesture">  | 
            
| 304 | 211 | 
                <connections>  | 
            
| 305 | 
                - <action selector="navigationToGroupNameModification:" destination="s9X-RR-Rat" id="R9K-8v-b14"/>  | 
            |
| 212 | 
                + <action selector="navigateToGroupNameModification:" destination="s9X-RR-Rat" id="R9K-8v-b14"/>  | 
            |
| 306 | 213 | 
                </connections>  | 
            
| 307 | 214 | 
                </tapGestureRecognizer>  | 
            
| 308 | 215 | 
                <tapGestureRecognizer id="PAc-yU-TO1" userLabel="GroupMemeberGesture">  | 
            
| 309 | 216 | 
                <connections>  | 
            
| 310 | 
                - <action selector="navigationToGroupMember:" destination="s9X-RR-Rat" id="V81-eM-vdl"/>  | 
            |
| 217 | 
                + <action selector="navigateToGroupMember:" destination="s9X-RR-Rat" id="V81-eM-vdl"/>  | 
            |
| 311 | 218 | 
                </connections>  | 
            
| 312 | 219 | 
                </tapGestureRecognizer>  | 
            
| 313 | 220 | 
                <tapGestureRecognizer id="CLv-er-MwX" userLabel="GroupQRGesture">  | 
            
                @@ -377,7 +284,7 @@  | 
            ||
| 377 | 284 | 
                </connections>  | 
            
| 378 | 285 | 
                </tapGestureRecognizer>  | 
            
| 379 | 286 | 
                </objects>  | 
            
| 380 | 
                - <point key="canvasLocation" x="665.60000000000002" y="277.06146926536735"/>  | 
            |
| 287 | 
                + <point key="canvasLocation" x="-106" y="926"/>  | 
            |
| 381 | 288 | 
                </scene>  | 
            
| 382 | 289 | 
                <!--GroupMemberViewController-->  | 
            
| 383 | 290 | 
                <scene sceneID="LEa-gB-9eo">  | 
            
                @@ -486,7 +393,7 @@  | 
            ||
| 486 | 393 | 
                </viewController>  | 
            
| 487 | 394 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="gLf-lq-mC0" sceneMemberID="firstResponder"/>  | 
            
| 488 | 395 | 
                </objects>  | 
            
| 489 | 
                - <point key="canvasLocation" x="665.60000000000002" y="1461.7691154422789"/>  | 
            |
| 396 | 
                + <point key="canvasLocation" x="-106" y="1622"/>  | 
            |
| 490 | 397 | 
                </scene>  | 
            
| 491 | 398 | 
                </scenes>  | 
            
| 492 | 399 | 
                <resources>  | 
            
                @@ -22,15 +22,15 @@ class GroupDetailCoordinator: Coordinator {
               | 
            ||
| 22 | 22 | 
                }  | 
            
| 23 | 23 | 
                 | 
            
| 24 | 24 | 
                 extension GroupDetailCoordinator: GroupDetailViewModelDelegate {
               | 
            
| 25 | 
                -    func navigationToRootViewController() {
               | 
            |
| 25 | 
                +    func navigateToRootViewController() {
               | 
            |
| 26 | 26 | 
                navigationController.popToRootViewController(animated: true)  | 
            
| 27 | 27 | 
                }  | 
            
| 28 | 28 | 
                 | 
            
| 29 | 
                -    func navigationToGroupMember(_ item: GroupDetailItem) {
               | 
            |
| 29 | 
                +    func navigateToGroupMember(_ item: GroupDetailItem) {
               | 
            |
| 30 | 30 | 
                navigationController.pushViewController(makeGroupMemberViewController(item))  | 
            
| 31 | 31 | 
                }  | 
            
| 32 | 32 | 
                 | 
            
| 33 | 
                -    func navigationToGroupNameModification(_ item: GroupDetailItem) {
               | 
            |
| 33 | 
                +    func navigateToGroupNameModification(_ item: GroupDetailItem) {
               | 
            |
| 34 | 34 | 
                navigationController.pushViewController(makeGroupNameModificationViewController(item))  | 
            
| 35 | 35 | 
                }  | 
            
| 36 | 36 | 
                }  | 
            
                @@ -92,12 +92,12 @@ fileprivate extension GroupDetailViewController {
               | 
            ||
| 92 | 92 | 
                 | 
            
| 93 | 93 | 
                /// storyboard action  | 
            
| 94 | 94 | 
                 extension GroupDetailViewController {
               | 
            
| 95 | 
                -    @IBAction func navigationToGroupMember(_ sender: UITapGestureRecognizer) {
               | 
            |
| 96 | 
                - viewModel.navigationToGroupMember()  | 
            |
| 95 | 
                +    @IBAction func navigateToGroupMember(_ sender: UITapGestureRecognizer) {
               | 
            |
| 96 | 
                + viewModel.navigateToGroupMember()  | 
            |
| 97 | 97 | 
                }  | 
            
| 98 | 98 | 
                 | 
            
| 99 | 
                -    @IBAction func navigationToGroupNameModification(_ sender: UITapGestureRecognizer) {
               | 
            |
| 100 | 
                - viewModel.navigationToGroupNameModification()  | 
            |
| 99 | 
                +    @IBAction func navigateToGroupNameModification(_ sender: UITapGestureRecognizer) {
               | 
            |
| 100 | 
                + viewModel.navigateToGroupNameModification()  | 
            |
| 101 | 101 | 
                }  | 
            
| 102 | 102 | 
                 | 
            
| 103 | 103 | 
                     @IBAction func presentGroupQR(_ sender: UITapGestureRecognizer) {
               | 
            
                @@ -28,12 +28,12 @@ final class GroupMemberCell: UITableViewCell {
               | 
            ||
| 28 | 28 | 
                var item = GroupMemberItem(json: [:])  | 
            
| 29 | 29 | 
                 | 
            
| 30 | 30 | 
                // MARK: init interface  | 
            
| 31 | 
                -    func setInfo(_ model: GroupMemberItem, isAdmin: Bool) {
               | 
            |
| 32 | 
                - item = model  | 
            |
| 33 | 
                - meberName.text = model.nickname  | 
            |
| 34 | 
                - uerImage.setImage(model.avatar, placeholder: UIImage.defaultAvatar)  | 
            |
| 35 | 
                - isManager.isHidden = !model.admin  | 
            |
| 36 | 
                - deleteConstraint.constant = !isAdmin || model.admin ? -32 : 12  | 
            |
| 31 | 
                +    func setInfo(_ info: GroupMemberItem, isAdmin: Bool) {
               | 
            |
| 32 | 
                + item = info  | 
            |
| 33 | 
                + meberName.text = info.nickname  | 
            |
| 34 | 
                + uerImage.setImage(info.avatar, placeholder: UIImage.defaultAvatar)  | 
            |
| 35 | 
                + isManager.isHidden = !info.admin  | 
            |
| 36 | 
                + deleteConstraint.constant = !isAdmin || info.admin ? -35 : 12  | 
            |
| 37 | 37 | 
                }  | 
            
| 38 | 38 | 
                 | 
            
| 39 | 39 | 
                // MARK: Storyboard button  | 
            
                @@ -19,7 +19,9 @@ final class GroupViewController: UIViewController {
               | 
            ||
| 19 | 19 | 
                // MARK: Storyboard property  | 
            
| 20 | 20 | 
                @IBOutlet weak var collectionView: UICollectionView!  | 
            
| 21 | 21 | 
                @IBOutlet weak var photographBtn: UIButton!  | 
            
| 22 | 
                -  | 
            |
| 22 | 
                + @IBOutlet weak var emptyView: UIStackView!  | 
            |
| 23 | 
                + @IBOutlet weak var qrImageView: UIImageView!  | 
            |
| 24 | 
                +  | 
            |
| 23 | 25 | 
                // MARK: custom UI property  | 
            
| 24 | 26 | 
                     var navigationBarView: UIView = {
               | 
            
| 25 | 27 | 
                let view = UIView()  | 
            
                @@ -87,6 +89,9 @@ fileprivate extension GroupViewController {
               | 
            ||
| 87 | 89 | 
                }  | 
            
| 88 | 90 | 
                 | 
            
| 89 | 91 | 
                     func binding() {
               | 
            
| 92 | 
                + bindViewModelToEmptyView()  | 
            |
| 93 | 
                + bindViewModelToQRImageView()  | 
            |
| 94 | 
                +  | 
            |
| 90 | 95 | 
                bindViewModelToRefreshing()  | 
            
| 91 | 96 | 
                bindCollectionViewDelegate()  | 
            
| 92 | 97 | 
                bindViewModelToCollectionView()  | 
            
                @@ -95,6 +100,14 @@ fileprivate extension GroupViewController {
               | 
            ||
| 95 | 100 | 
                bindViewModelToNavigationBarTitle()  | 
            
| 96 | 101 | 
                }  | 
            
| 97 | 102 | 
                 | 
            
| 103 | 
                +    func bindViewModelToEmptyView() {
               | 
            |
| 104 | 
                + viewModel.hasData.bind(to: emptyView.rx.isHidden).disposed(by: disposeBag)  | 
            |
| 105 | 
                + }  | 
            |
| 106 | 
                +  | 
            |
| 107 | 
                +    func bindViewModelToQRImageView() {
               | 
            |
| 108 | 
                +        viewModel.groupItem.map { UIImage(qr: "https:api.pai.ai/g/\($0.group_id)") }.bind(to: qrImageView.rx.image).disposed(by: disposeBag)
               | 
            |
| 109 | 
                + }  | 
            |
| 110 | 
                +  | 
            |
| 98 | 111 | 
                     func bindViewModelToRefreshing() {
               | 
            
| 99 | 112 | 
                viewModel.isLoading  | 
            
| 100 | 113 | 
                             .subscribe(onNext: {[unowned self] flag in
               | 
            
                @@ -129,7 +142,6 @@ fileprivate extension GroupViewController {
               | 
            ||
| 129 | 142 | 
                                 guard let `self` = self else { return }
               | 
            
| 130 | 143 | 
                self.navigationBarViewImage.image = UIImage(named: avatar)  | 
            
| 131 | 144 | 
                }).disposed(by: disposeBag)  | 
            
| 132 | 
                -  | 
            |
| 133 | 145 | 
                }  | 
            
| 134 | 146 | 
                }  | 
            
| 135 | 147 | 
                 | 
            
                @@ -168,7 +180,7 @@ extension GroupViewController: NavigationBarInteractiveViewController {
               | 
            ||
| 168 | 180 | 
                let groupItem = viewModel.groupItem.value  | 
            
| 169 | 181 | 
                let alert = AlertViewController(style: .custom(GroupQRView(groupName: groupItem.group_name,  | 
            
| 170 | 182 | 
                groupAvatar: "Group\(groupItem.group_default_avatar)",  | 
            
| 171 | 
                - groupQR: "https:pai.ai/g/\(groupItem.group_id)"),  | 
            |
| 183 | 
                + groupQR: "https:api.pai.ai/g/\(groupItem.group_id)"),  | 
            |
| 172 | 184 | 
                AlertAnimator()) )  | 
            
| 173 | 185 | 
                presentController(alert)  | 
            
| 174 | 186 | 
                }  | 
            
                @@ -50,7 +50,8 @@ extension HomeCoordinator: HomeViewModelDelegate {
               | 
            ||
| 50 | 50 | 
                 | 
            
| 51 | 51 | 
                     func scanQR() {
               | 
            
| 52 | 52 | 
                let ctl = UIStoryboard.main.instantiateScanQRViewController()  | 
            
| 53 | 
                - homeViewController.pushController(ctl)  | 
            |
| 53 | 
                + ctl.viewModel.delegate = self  | 
            |
| 54 | 
                + navigationController.pushViewController(ctl)  | 
            |
| 54 | 55 | 
                }  | 
            
| 55 | 56 | 
                }  | 
            
| 56 | 57 | 
                 | 
            
                @@ -73,15 +74,26 @@ extension HomeCoordinator: CreateGroupViewControllerDelegate {
               | 
            ||
| 73 | 74 | 
                }  | 
            
| 74 | 75 | 
                 | 
            
| 75 | 76 | 
                 extension HomeCoordinator: CreateGroupViewModelDelegate {
               | 
            
| 76 | 
                -    func navigationToGroup(_ item: GroupItem) {
               | 
            |
| 77 | 
                +    func navigateToGroup(_ item: GroupItem) {
               | 
            |
| 77 | 78 | 
                         guard let vc = homeViewController.presentedViewController, vc.isMember(of: CreateGroupConfirmViewController.self) else { return }
               | 
            
| 78 | 79 | 
                vc.dismissController()  | 
            
| 79 | 80 | 
                 | 
            
| 80 | 81 | 
                let ctl = UIStoryboard.group.instantiateController(GroupViewController.self)  | 
            
| 82 | 
                + ctl.viewModel = GroupViewModel(groupItem: item)  | 
            |
| 81 | 83 | 
                let coordinator = GroupCoordinator(ctl,  | 
            
| 82 | 84 | 
                navigationController: navigationController)  | 
            
| 83 | 85 | 
                coordinators[.group] = coordinator  | 
            
| 86 | 
                + navigationController.pushViewController(ctl)  | 
            |
| 87 | 
                + }  | 
            |
| 88 | 
                +}  | 
            |
| 89 | 
                +  | 
            |
| 90 | 
                +extension HomeCoordinator: ScanQRViewModelDelegate {
               | 
            |
| 91 | 
                +    func navigateToGroupFromScanQR(_ item: GroupItem) {
               | 
            |
| 92 | 
                + let ctl = UIStoryboard.group.instantiateController(GroupViewController.self)  | 
            |
| 84 | 93 | 
                ctl.viewModel = GroupViewModel(groupItem: item)  | 
            
| 94 | 
                + let coordinator = GroupCoordinator(ctl,  | 
            |
| 95 | 
                + navigationController: navigationController)  | 
            |
| 96 | 
                + coordinators[.group] = coordinator  | 
            |
| 85 | 97 | 
                navigationController.pushViewController(ctl)  | 
            
| 86 | 98 | 
                }  | 
            
| 87 | 99 | 
                }  | 
            
                @@ -16,8 +16,6 @@ final class HomeViewController: UIViewController {
               | 
            ||
| 16 | 16 | 
                 | 
            
| 17 | 17 | 
                @IBOutlet weak var scanBtn: UIButton!  | 
            
| 18 | 18 | 
                @IBOutlet weak var createBtn: UIButton!  | 
            
| 19 | 
                - @IBOutlet weak var scanLabel: UILabel!  | 
            |
| 20 | 
                - @IBOutlet weak var createLabel: UILabel!  | 
            |
| 21 | 19 | 
                @IBOutlet weak var collectionView: UICollectionView!  | 
            
| 22 | 20 | 
                // MARK: data property  | 
            
| 23 | 21 | 
                fileprivate let disposeBag = DisposeBag()  | 
            
                @@ -30,6 +28,10 @@ final class HomeViewController: UIViewController {
               | 
            ||
| 30 | 28 | 
                initalize()  | 
            
| 31 | 29 | 
                }  | 
            
| 32 | 30 | 
                 | 
            
| 31 | 
                +    override func viewDidAppear(_ animated: Bool) {
               | 
            |
| 32 | 
                + super.viewDidAppear(animated)  | 
            |
| 33 | 
                + }  | 
            |
| 34 | 
                +  | 
            |
| 33 | 35 | 
                     func initalize() {
               | 
            
| 34 | 36 | 
                collectionView.register(UINib(nibName: "PhotoCell",  | 
            
| 35 | 37 | 
                bundle: Bundle(identifier: "com.Paiai-iOS")),  | 
            
                @@ -18,7 +18,7 @@  | 
            ||
| 18 | 18 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>  | 
            
| 19 | 19 | 
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>  | 
            
| 20 | 20 | 
                <subviews>  | 
            
| 21 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7XC-di-knu" customClass="QRCodeScanView" customModule="Paiai_iOS" customModuleProvider="target">  | 
            |
| 21 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7XC-di-knu" customClass="QRCodeScanView" customModule="PaiaiUIKit">  | 
            |
| 22 | 22 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>  | 
            
| 23 | 23 | 
                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 24 | 24 | 
                </view>  | 
            
                @@ -31,47 +31,54 @@  | 
            ||
| 31 | 31 | 
                <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 32 | 32 | 
                <nil key="highlightedColor"/>  | 
            
| 33 | 33 | 
                </label>  | 
            
| 34 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q8D-p5-28m">  | 
            |
| 34 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q8D-p5-28m" userLabel="Button Group">  | 
            |
| 35 | 35 | 
                <rect key="frame" x="0.0" y="547" width="375" height="120"/>  | 
            
| 36 | 36 | 
                <subviews>  | 
            
| 37 | 
                - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rAd-6a-QN5">  | 
            |
| 38 | 
                - <rect key="frame" x="212" y="30" width="126" height="126"/>  | 
            |
| 39 | 
                - <state key="normal" image="BTN-flash"/>  | 
            |
| 40 | 
                - <connections>  | 
            |
| 41 | 
                - <action selector="openLight" destination="xAo-Yl-fd5" eventType="touchUpInside" id="S8Z-U4-bVm"/>  | 
            |
| 42 | 
                - </connections>  | 
            |
| 43 | 
                - </button>  | 
            |
| 44 | 
                - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WMh-c4-xbf">  | 
            |
| 45 | 
                - <rect key="frame" x="37" y="30" width="126" height="126"/>  | 
            |
| 46 | 
                - <state key="normal" image="BTN-photoAlbum"/>  | 
            |
| 47 | 
                - <connections>  | 
            |
| 48 | 
                - <action selector="chooseFromSYSPhoto" destination="xAo-Yl-fd5" eventType="touchUpInside" id="U7Z-Vq-2r2"/>  | 
            |
| 49 | 
                - </connections>  | 
            |
| 50 | 
                - </button>  | 
            |
| 51 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="相册" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kS9-OM-EAv">  | 
            |
| 52 | 
                - <rect key="frame" x="86.5" y="166" width="27" height="16"/>  | 
            |
| 53 | 
                - <fontDescription key="fontDescription" type="system" pointSize="13"/>  | 
            |
| 54 | 
                - <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 55 | 
                - <nil key="highlightedColor"/>  | 
            |
| 56 | 
                - </label>  | 
            |
| 57 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="开灯" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3ge-7H-lZn">  | 
            |
| 58 | 
                - <rect key="frame" x="261.5" y="166" width="27" height="16"/>  | 
            |
| 59 | 
                - <fontDescription key="fontDescription" type="system" pointSize="13"/>  | 
            |
| 60 | 
                - <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 61 | 
                - <nil key="highlightedColor"/>  | 
            |
| 62 | 
                - </label>  | 
            |
| 37 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="8lh-CA-1SM">  | 
            |
| 38 | 
                + <rect key="frame" x="37" y="-16" width="126" height="152"/>  | 
            |
| 39 | 
                + <subviews>  | 
            |
| 40 | 
                + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="q7U-7O-6Og">  | 
            |
| 41 | 
                + <rect key="frame" x="0.0" y="0.0" width="126" height="126"/>  | 
            |
| 42 | 
                + <state key="normal" image="BTN-photoAlbum"/>  | 
            |
| 43 | 
                + <connections>  | 
            |
| 44 | 
                + <action selector="openPhotoLibrary:" destination="xAo-Yl-fd5" eventType="touchUpInside" id="z8x-bJ-FA8"/>  | 
            |
| 45 | 
                + </connections>  | 
            |
| 46 | 
                + </button>  | 
            |
| 47 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="相册" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QXR-Bg-aZe">  | 
            |
| 48 | 
                + <rect key="frame" x="49.5" y="136" width="27" height="16"/>  | 
            |
| 49 | 
                + <fontDescription key="fontDescription" type="system" pointSize="13"/>  | 
            |
| 50 | 
                + <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 51 | 
                + <nil key="highlightedColor"/>  | 
            |
| 52 | 
                + </label>  | 
            |
| 53 | 
                + </subviews>  | 
            |
| 54 | 
                + </stackView>  | 
            |
| 55 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="AkM-en-2b0">  | 
            |
| 56 | 
                + <rect key="frame" x="212" y="-16" width="126" height="152"/>  | 
            |
| 57 | 
                + <subviews>  | 
            |
| 58 | 
                + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yvI-5s-SNa">  | 
            |
| 59 | 
                + <rect key="frame" x="0.0" y="0.0" width="126" height="126"/>  | 
            |
| 60 | 
                + <state key="normal" image="BTN-flash"/>  | 
            |
| 61 | 
                + <connections>  | 
            |
| 62 | 
                + <action selector="chooseFromSYSPhoto" destination="xAo-Yl-fd5" eventType="touchUpInside" id="5MC-Mh-hVr"/>  | 
            |
| 63 | 
                + <action selector="openLight" destination="xAo-Yl-fd5" eventType="touchUpInside" id="3CZ-Mz-UhH"/>  | 
            |
| 64 | 
                + </connections>  | 
            |
| 65 | 
                + </button>  | 
            |
| 66 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="相册" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q3p-9D-GA5" userLabel="开灯">  | 
            |
| 67 | 
                + <rect key="frame" x="49.5" y="136" width="27" height="16"/>  | 
            |
| 68 | 
                + <fontDescription key="fontDescription" type="system" pointSize="13"/>  | 
            |
| 69 | 
                + <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 70 | 
                + <nil key="highlightedColor"/>  | 
            |
| 71 | 
                + </label>  | 
            |
| 72 | 
                + </subviews>  | 
            |
| 73 | 
                + </stackView>  | 
            |
| 63 | 74 | 
                </subviews>  | 
            
| 64 | 75 | 
                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.61263020833333337" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 65 | 76 | 
                <constraints>  | 
            
| 77 | 
                + <constraint firstItem="AkM-en-2b0" firstAttribute="centerX" secondItem="q8D-p5-28m" secondAttribute="centerX" multiplier="2.2:1.5" id="00d-8F-8A8"/>  | 
            |
| 78 | 
                + <constraint firstItem="8lh-CA-1SM" firstAttribute="centerX" secondItem="q8D-p5-28m" secondAttribute="centerX" multiplier="0.8:1.5" id="8Y5-Ty-dQU"/>  | 
            |
| 66 | 79 | 
                <constraint firstAttribute="height" constant="120" id="C3L-jp-KPg"/>  | 
            
| 67 | 
                - <constraint firstItem="3ge-7H-lZn" firstAttribute="centerY" secondItem="kS9-OM-EAv" secondAttribute="centerY" id="Eg5-nH-ESw"/>  | 
            |
| 68 | 
                - <constraint firstItem="rAd-6a-QN5" firstAttribute="centerX" secondItem="q8D-p5-28m" secondAttribute="centerX" multiplier="2.2:1.5" id="OvL-8a-H6B"/>  | 
            |
| 69 | 
                - <constraint firstItem="kS9-OM-EAv" firstAttribute="centerX" secondItem="WMh-c4-xbf" secondAttribute="centerX" id="RX1-NM-6ql"/>  | 
            |
| 70 | 
                - <constraint firstItem="3ge-7H-lZn" firstAttribute="centerX" secondItem="rAd-6a-QN5" secondAttribute="centerX" id="SeW-CQ-8PV"/>  | 
            |
| 71 | 
                - <constraint firstItem="rAd-6a-QN5" firstAttribute="top" secondItem="q8D-p5-28m" secondAttribute="top" constant="30" id="lEh-G7-ra7"/>  | 
            |
| 72 | 
                - <constraint firstItem="kS9-OM-EAv" firstAttribute="top" secondItem="WMh-c4-xbf" secondAttribute="bottom" constant="10" id="lc4-9K-GH0"/>  | 
            |
| 73 | 
                - <constraint firstItem="WMh-c4-xbf" firstAttribute="centerX" secondItem="q8D-p5-28m" secondAttribute="centerX" multiplier="0.8:1.5" id="oAa-Vb-s7j"/>  | 
            |
| 74 | 
                - <constraint firstItem="WMh-c4-xbf" firstAttribute="centerY" secondItem="rAd-6a-QN5" secondAttribute="centerY" id="svb-nJ-3Va"/>  | 
            |
| 80 | 
                + <constraint firstItem="8lh-CA-1SM" firstAttribute="centerY" secondItem="q8D-p5-28m" secondAttribute="centerY" id="MEn-bu-Ss6"/>  | 
            |
| 81 | 
                + <constraint firstItem="AkM-en-2b0" firstAttribute="centerY" secondItem="q8D-p5-28m" secondAttribute="centerY" id="ccs-Xt-wa5"/>  | 
            |
| 75 | 82 | 
                </constraints>  | 
            
| 76 | 83 | 
                </view>  | 
            
| 77 | 84 | 
                </subviews>  | 
            
                @@ -80,7 +87,7 @@  | 
            ||
| 80 | 87 | 
                <constraint firstItem="7XC-di-knu" firstAttribute="height" secondItem="EBW-ey-zDN" secondAttribute="height" id="1W3-tY-WR7"/>  | 
            
| 81 | 88 | 
                <constraint firstItem="7XC-di-knu" firstAttribute="centerY" secondItem="EBW-ey-zDN" secondAttribute="centerY" id="4iq-Mx-Dgn"/>  | 
            
| 82 | 89 | 
                <constraint firstItem="q8D-p5-28m" firstAttribute="leading" secondItem="5ji-s5-pMy" secondAttribute="leading" id="7pa-0E-902"/>  | 
            
| 83 | 
                - <constraint firstItem="5ji-s5-pMy" firstAttribute="bottom" secondItem="q8D-p5-28m" secondAttribute="bottom" id="OlH-gg-PAG"/>  | 
            |
| 90 | 
                + <constraint firstAttribute="bottom" secondItem="q8D-p5-28m" secondAttribute="bottom" id="OlH-gg-PAG"/>  | 
            |
| 84 | 91 | 
                <constraint firstItem="7XC-di-knu" firstAttribute="width" secondItem="EBW-ey-zDN" secondAttribute="width" id="Smj-tP-9h1"/>  | 
            
| 85 | 92 | 
                <constraint firstItem="IUv-gn-PD8" firstAttribute="centerX" secondItem="5ji-s5-pMy" secondAttribute="centerX" id="aJ9-AF-OhC"/>  | 
            
| 86 | 93 | 
                <constraint firstItem="7XC-di-knu" firstAttribute="centerX" secondItem="5ji-s5-pMy" secondAttribute="centerX" id="c15-dp-2dX"/>  | 
            
                @@ -91,13 +98,12 @@  | 
            ||
| 91 | 98 | 
                </view>  | 
            
| 92 | 99 | 
                <navigationItem key="navigationItem" id="OV6-lQ-3b0"/>  | 
            
| 93 | 100 | 
                <connections>  | 
            
| 94 | 
                - <outlet property="lightLabel" destination="3ge-7H-lZn" id="gyD-hT-m5I"/>  | 
            |
| 95 | 101 | 
                <outlet property="scanView" destination="7XC-di-knu" id="Nbf-fG-L8b"/>  | 
            
| 96 | 102 | 
                </connections>  | 
            
| 97 | 103 | 
                </viewController>  | 
            
| 98 | 104 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="Egx-Nh-Avl" userLabel="First Responder" sceneMemberID="firstResponder"/>  | 
            
| 99 | 105 | 
                </objects>  | 
            
| 100 | 
                - <point key="canvasLocation" x="2804" y="-128.18590704647679"/>  | 
            |
| 106 | 
                + <point key="canvasLocation" x="3034" y="-49"/>  | 
            |
| 101 | 107 | 
                </scene>  | 
            
| 102 | 108 | 
                <!--Home View Controller-->  | 
            
| 103 | 109 | 
                <scene sceneID="tne-QT-ifu">  | 
            
                @@ -113,34 +119,37 @@  | 
            ||
| 113 | 119 | 
                <collectionViewLayout key="collectionViewLayout" id="0AU-E8-zrg" customClass="WaterfallFlowLayout" customModule="PaiaiUIKit"/>  | 
            
| 114 | 120 | 
                <cells/>  | 
            
| 115 | 121 | 
                </collectionView>  | 
            
| 116 | 
                - <button contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7sh-KD-Wgc">  | 
            |
| 117 | 
                - <rect key="frame" x="303" y="536" width="64" height="64"/>  | 
            |
| 118 | 
                - <constraints>  | 
            |
| 119 | 
                - <constraint firstAttribute="width" constant="64" id="6uz-fL-QnX"/>  | 
            |
| 120 | 
                - <constraint firstAttribute="height" constant="64" id="fVK-Un-AnR"/>  | 
            |
| 121 | 
                - </constraints>  | 
            |
| 122 | 
                - <state key="normal" image="BTN-scanQR"/>  | 
            |
| 123 | 
                - <state key="selected" image="BTN-扫码-press"/>  | 
            |
| 124 | 
                - </button>  | 
            |
| 125 | 
                - <button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EqW-Tv-dAo">  | 
            |
| 126 | 
                - <rect key="frame" x="303" y="603" width="64" height="64"/>  | 
            |
| 127 | 
                - <constraints>  | 
            |
| 128 | 
                - <constraint firstAttribute="height" constant="64" id="6oe-ry-LNq"/>  | 
            |
| 129 | 
                - <constraint firstAttribute="width" constant="64" id="bCz-yX-g9j"/>  | 
            |
| 130 | 
                - </constraints>  | 
            |
| 131 | 
                - <state key="normal" image="BTN-add"/>  | 
            |
| 132 | 
                - <state key="selected" image="BTN-新增-press"/>  | 
            |
| 133 | 
                - </button>  | 
            |
| 122 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="3" translatesAutoresizingMaskIntoConstraints="NO" id="cKo-t0-fYb">  | 
            |
| 123 | 
                + <rect key="frame" x="303" y="530" width="64" height="131"/>  | 
            |
| 124 | 
                + <subviews>  | 
            |
| 125 | 
                + <button contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9N2-vw-PuD">  | 
            |
| 126 | 
                + <rect key="frame" x="0.0" y="0.0" width="64" height="64"/>  | 
            |
| 127 | 
                + <constraints>  | 
            |
| 128 | 
                + <constraint firstAttribute="width" constant="64" id="ZvU-38-X8E"/>  | 
            |
| 129 | 
                + <constraint firstAttribute="height" constant="64" id="tmA-ui-pTy"/>  | 
            |
| 130 | 
                + </constraints>  | 
            |
| 131 | 
                + <state key="normal" image="BTN-scanQR"/>  | 
            |
| 132 | 
                + <state key="selected" image="BTN-扫码-press"/>  | 
            |
| 133 | 
                + </button>  | 
            |
| 134 | 
                + <button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="f1p-NO-R2Q">  | 
            |
| 135 | 
                + <rect key="frame" x="0.0" y="67" width="64" height="64"/>  | 
            |
| 136 | 
                + <constraints>  | 
            |
| 137 | 
                + <constraint firstAttribute="height" constant="64" id="4PT-EP-AZd"/>  | 
            |
| 138 | 
                + <constraint firstAttribute="width" constant="64" id="B4F-Wn-0g0"/>  | 
            |
| 139 | 
                + </constraints>  | 
            |
| 140 | 
                + <state key="normal" image="BTN-add"/>  | 
            |
| 141 | 
                + <state key="selected" image="BTN-新增-press"/>  | 
            |
| 142 | 
                + </button>  | 
            |
| 143 | 
                + </subviews>  | 
            |
| 144 | 
                + </stackView>  | 
            |
| 134 | 145 | 
                </subviews>  | 
            
| 135 | 146 | 
                <color key="backgroundColor" red="0.8784313725490196" green="0.8784313725490196" blue="0.8784313725490196" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 136 | 147 | 
                <gestureRecognizers/>  | 
            
| 137 | 148 | 
                <constraints>  | 
            
| 138 | 
                - <constraint firstItem="WrX-F2-609" firstAttribute="trailing" secondItem="EqW-Tv-dAo" secondAttribute="trailing" constant="8" id="8xh-Ra-Ka9"/>  | 
            |
| 149 | 
                + <constraint firstItem="WrX-F2-609" firstAttribute="trailing" secondItem="cKo-t0-fYb" secondAttribute="trailing" constant="8" id="PWG-Fo-tUz"/>  | 
            |
| 139 | 150 | 
                <constraint firstItem="jOc-hp-K8U" firstAttribute="leading" secondItem="WrX-F2-609" secondAttribute="leading" id="Qu3-TE-tcJ"/>  | 
            
| 140 | 
                - <constraint firstItem="WrX-F2-609" firstAttribute="bottom" secondItem="EqW-Tv-dAo" secondAttribute="bottom" id="TQF-Gj-zB1"/>  | 
            |
| 141 | 
                - <constraint firstItem="7sh-KD-Wgc" firstAttribute="centerX" secondItem="EqW-Tv-dAo" secondAttribute="centerX" id="dbL-Gy-iB4"/>  | 
            |
| 151 | 
                + <constraint firstItem="WrX-F2-609" firstAttribute="bottom" secondItem="cKo-t0-fYb" secondAttribute="bottom" constant="6" id="T1b-BO-JPL"/>  | 
            |
| 142 | 152 | 
                <constraint firstItem="WrX-F2-609" firstAttribute="trailing" secondItem="jOc-hp-K8U" secondAttribute="trailing" id="iMD-9d-Ih2"/>  | 
            
| 143 | 
                - <constraint firstItem="EqW-Tv-dAo" firstAttribute="top" secondItem="7sh-KD-Wgc" secondAttribute="bottom" constant="3" id="oUu-Fy-hJV"/>  | 
            |
| 144 | 153 | 
                <constraint firstItem="jOc-hp-K8U" firstAttribute="top" secondItem="WrX-F2-609" secondAttribute="top" id="pOC-6k-2LI"/>  | 
            
| 145 | 154 | 
                <constraint firstAttribute="bottom" secondItem="jOc-hp-K8U" secondAttribute="bottom" id="xM5-JS-BLE"/>  | 
            
| 146 | 155 | 
                </constraints>  | 
            
                @@ -150,13 +159,13 @@  | 
            ||
| 150 | 159 | 
                <navigationItem key="navigationItem" id="blv-Da-mEq"/>  | 
            
| 151 | 160 | 
                <connections>  | 
            
| 152 | 161 | 
                <outlet property="collectionView" destination="jOc-hp-K8U" id="4Hm-wP-XjU"/>  | 
            
| 153 | 
                - <outlet property="createBtn" destination="EqW-Tv-dAo" id="Q3K-6N-47U"/>  | 
            |
| 154 | 
                - <outlet property="scanBtn" destination="7sh-KD-Wgc" id="oZT-w4-Ddq"/>  | 
            |
| 162 | 
                + <outlet property="createBtn" destination="f1p-NO-R2Q" id="wDa-iP-DeC"/>  | 
            |
| 163 | 
                + <outlet property="scanBtn" destination="9N2-vw-PuD" id="tdK-KP-5Vh"/>  | 
            |
| 155 | 164 | 
                </connections>  | 
            
| 156 | 165 | 
                </viewController>  | 
            
| 157 | 166 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>  | 
            
| 158 | 167 | 
                </objects>  | 
            
| 159 | 
                - <point key="canvasLocation" x="1705" y="-152"/>  | 
            |
| 168 | 
                + <point key="canvasLocation" x="2356" y="-49"/>  | 
            |
| 160 | 169 | 
                </scene>  | 
            
| 161 | 170 | 
                <!--CreateGroupViewController-->  | 
            
| 162 | 171 | 
                <scene sceneID="AAe-LB-J2k">  | 
            
                @@ -251,7 +260,7 @@  | 
            ||
| 251 | 260 | 
                </viewController>  | 
            
| 252 | 261 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="7bb-Fp-aIh" userLabel="First Responder" sceneMemberID="firstResponder"/>  | 
            
| 253 | 262 | 
                </objects>  | 
            
| 254 | 
                - <point key="canvasLocation" x="4628" y="80.50974512743629"/>  | 
            |
| 263 | 
                + <point key="canvasLocation" x="4354" y="-49"/>  | 
            |
| 255 | 264 | 
                </scene>  | 
            
| 256 | 265 | 
                <!--CreateGroupConfirmViewController-->  | 
            
| 257 | 266 | 
                <scene sceneID="zhC-tX-7HT">  | 
            
                @@ -369,7 +378,7 @@  | 
            ||
| 369 | 378 | 
                </viewController>  | 
            
| 370 | 379 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="hw0-Gp-7zQ" userLabel="First Responder" sceneMemberID="firstResponder"/>  | 
            
| 371 | 380 | 
                </objects>  | 
            
| 372 | 
                - <point key="canvasLocation" x="3847.1999999999998" y="80.50974512743629"/>  | 
            |
| 381 | 
                + <point key="canvasLocation" x="3694" y="-49"/>  | 
            |
| 373 | 382 | 
                </scene>  | 
            
| 374 | 383 | 
                <!--LoginViewController-->  | 
            
| 375 | 384 | 
                <scene sceneID="ETR-Op-aEq">  | 
            
                @@ -15,7 +15,6 @@ final class ScanQRViewController: UIViewController {
               | 
            ||
| 15 | 15 | 
                 | 
            
| 16 | 16 | 
                // MARK: Storyboard property  | 
            
| 17 | 17 | 
                @IBOutlet weak var scanView: QRCodeScanView!  | 
            
| 18 | 
                - @IBOutlet weak var lightLabel: UILabel!  | 
            |
| 19 | 18 | 
                 | 
            
| 20 | 19 | 
                // MARK: parameter property  | 
            
| 21 | 20 | 
                var viewModel = ScanQRViewModel()  | 
            
                @@ -24,108 +23,46 @@ final class ScanQRViewController: UIViewController {
               | 
            ||
| 24 | 23 | 
                // MARK: view function  | 
            
| 25 | 24 | 
                     override func viewDidLoad() {
               | 
            
| 26 | 25 | 
                super.viewDidLoad()  | 
            
| 27 | 
                -// navigationController?.navigationBar.setBackgroundImage(UIImage.imageWithColor(UIColor.black), for: .default)  | 
            |
| 28 | 26 | 
                scanView.delegate = self  | 
            
| 27 | 
                + viewModel.join(code: "http://pai.ai/g/SpA5be3")  | 
            |
| 29 | 28 | 
                }  | 
            
| 30 | 
                -  | 
            |
| 29 | 
                +  | 
            |
| 30 | 
                +    func setNavigationBar() {
               | 
            |
| 31 | 
                + title = "二维码"  | 
            |
| 32 | 
                + navigationController?.navigationBar.setBackgroundImage(UIImage.Navigation.blackBackground, for: .default)  | 
            |
| 33 | 
                + }  | 
            |
| 34 | 
                +  | 
            |
| 31 | 35 | 
                     override func viewWillAppear(_ animated: Bool) {
               | 
            
| 32 | 
                - super.viewWillAppear(true)  | 
            |
| 33 | 
                -// titleWithbackBar = "二维码"  | 
            |
| 36 | 
                + super.viewWillAppear(animated)  | 
            |
| 37 | 
                + setNavigationBar()  | 
            |
| 34 | 38 | 
                }  | 
            
| 35 | 39 | 
                 | 
            
| 36 | 
                - // MARK: Storyboard button function  | 
            |
| 37 | 
                -    @IBAction func chooseFromSYSPhoto() {
               | 
            |
| 38 | 
                - scanView.openPhotoLibrary(ctl: self)  | 
            |
| 40 | 
                +    override func viewWillDisappear(_ animated: Bool) {
               | 
            |
| 41 | 
                + super.viewWillDisappear(animated)  | 
            |
| 42 | 
                + navigationController?.navigationBar.setBackgroundImage(UIImage.Navigation.background, for: .default)  | 
            |
| 39 | 43 | 
                }  | 
            
| 44 | 
                +  | 
            |
| 45 | 
                +}  | 
            |
| 40 | 46 | 
                 | 
            
| 41 | 
                -    @IBAction func openLight() {
               | 
            |
| 42 | 
                - scanView.openLight()  | 
            |
| 47 | 
                +/// storyboard button action  | 
            |
| 48 | 
                +extension ScanQRViewController {
               | 
            |
| 49 | 
                +    @IBAction func openPhotoLibrary(_ sender: UIButton) {
               | 
            |
| 50 | 
                + scanView.openPhotoLibrary(ctl: self)  | 
            |
| 43 | 51 | 
                }  | 
            
| 44 | 52 | 
                 | 
            
| 45 | 
                -  | 
            |
| 53 | 
                +    @IBAction func openLight(_ sender: UIButton) {
               | 
            |
| 54 | 
                + scanView.openLight()  | 
            |
| 55 | 
                + }  | 
            |
| 46 | 56 | 
                }  | 
            
| 47 | 57 | 
                 | 
            
| 48 | 58 | 
                // MARK: read QR message  | 
            
| 49 | 59 | 
                // MARK: custom delegate function  | 
            
| 50 | 60 | 
                 extension ScanQRViewController: QRCodeScanViewDelegate {
               | 
            
| 51 | 
                -    func scanView(_ scanView: QRCodeScanView, didFinshWithError error: NSError?) {
               | 
            |
| 52 | 
                -  | 
            |
| 53 | 
                - }  | 
            |
| 61 | 
                +    func scanView(_ scanView: QRCodeScanView, didFinshWithError error: NSError?) {}
               | 
            |
| 54 | 62 | 
                 | 
            
| 55 | 63 | 
                     func scanView(_ scanner: QRCodeScanView, receivedScanResult: QRCodeScanResult) {
               | 
            
| 56 | 64 | 
                viewModel.join(code: receivedScanResult.result)  | 
            
| 57 | 65 | 
                }  | 
            
| 58 | 
                -  | 
            |
| 59 | 
                -    func addToTourGroup(group_id: String) {
               | 
            |
| 60 | 
                -//        if user_phone.isEmpty {
               | 
            |
| 61 | 
                -// let phone = NSString(string: user_phone).integerValue  | 
            |
| 62 | 
                -// let params = ["admin_id": group_id, "user_id": SharedUserInfo.userId, "authority": authority, "name": user_name, "phone": phone ] as [String: AnyObject]  | 
            |
| 63 | 
                -  | 
            |
| 64 | 
                -// let request = GroupNetworkRequest(path: .joinTourGroup, parameter: params)  | 
            |
| 65 | 
                -//            NetworkApi.share.post(request: request, handler: { (res) in
               | 
            |
| 66 | 
                -// let ctl = UIStoryboard.main.instantiateController(GroupViewController.self)  | 
            |
| 67 | 
                -// ctl.isCreate = true  | 
            |
| 68 | 
                -// ctl.isScan = true  | 
            |
| 69 | 
                -// ctl.groupModel = res[0]  | 
            |
| 70 | 
                -// self.navigationController?.pushViewController(ctl, animated: true)  | 
            |
| 71 | 
                -// })  | 
            |
| 72 | 
                -//        } else {
               | 
            |
| 73 | 
                -// let ctl = UIStoryboard.main.instantiateController(PersonInformationController.self)  | 
            |
| 74 | 
                -// ctl.admin_id = group_id  | 
            |
| 75 | 
                -// navigationController?.pushViewController(ctl, animated: true)  | 
            |
| 76 | 
                -// }  | 
            |
| 77 | 
                - }  | 
            |
| 78 | 
                -  | 
            |
| 79 | 
                -    func addToGroup(_ code: String) {
               | 
            |
| 80 | 
                -// let strs = code.components(separatedBy: "/")  | 
            |
| 81 | 
                -//        guard strs.count > 2, var group_id = strs.last else {
               | 
            |
| 82 | 
                -// FFToastView.showToast(inView: self.view, withText: "读取失败")  | 
            |
| 83 | 
                -// return  | 
            |
| 84 | 
                -// }  | 
            |
| 85 | 
                -// FFToastView.showLoadingToast(inView: view, blockSuperView: true)  | 
            |
| 86 | 
                -// let flag = strs[strs.count-2]  | 
            |
| 87 | 
                -//        guard flag == "s" || flag == "g" || flag == "tgu" else {
               | 
            |
| 88 | 
                -// FFToastView.showToast(inView: self.view, withText: "读取失败")  | 
            |
| 89 | 
                -// return  | 
            |
| 90 | 
                -// }  | 
            |
| 91 | 
                -//        if flag == "tgu" {
               | 
            |
| 92 | 
                -// addToTourGroup(group_id: group_id)  | 
            |
| 93 | 
                -// return  | 
            |
| 94 | 
                -// }  | 
            |
| 95 | 
                -// let isGroup = flag == "g"  | 
            |
| 96 | 
                -// let path = isGroup ? Interfaces.joinGroup : Interfaces.joinSession  | 
            |
| 97 | 
                -// let idName = isGroup ? "group_id" : "session_id"  | 
            |
| 98 | 
                -// let lensman_id = (group_id.components(separatedBy: "?").last ?? "").components(separatedBy: "=").last ?? ""  | 
            |
| 99 | 
                -// group_id = group_id.components(separatedBy: "?").first ?? ""  | 
            |
| 100 | 
                -// let params = ["user_id": SharedUserInfo.userId, idName: group_id, "nickname": SharedUserInfo.name, "lensman_id" : lensman_id] as [String: AnyObject]  | 
            |
| 101 | 
                -  | 
            |
| 102 | 
                -// let request = GroupNetworkRequest(path: path, parameter: params)  | 
            |
| 103 | 
                -//        NetworkApi.share.post(request: request, handler: { (res) in
               | 
            |
| 104 | 
                -// let ctl = UIStoryboard.main.instantiateController(GroupViewController.self)  | 
            |
| 105 | 
                -// ctl.isCreate = true  | 
            |
| 106 | 
                -// ctl.isScan = true  | 
            |
| 107 | 
                -// ctl.groupModel = res[0]  | 
            |
| 108 | 
                -// self.navigationController?.pushViewController(ctl, animated: true)  | 
            |
| 109 | 
                -// FFToastView.hideLoadingToast()  | 
            |
| 110 | 
                -// })  | 
            |
| 111 | 
                - }  | 
            |
| 112 | 66 | 
                }  | 
            
| 113 | 67 | 
                 | 
            
| 114 | 
                -// MARK: imagePick delegate  | 
            |
| 115 | 
                -extension ScanQRViewController: UIImagePickerControllerDelegate {
               | 
            |
| 116 | 
                -  | 
            |
| 117 | 
                -    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String: AnyObject]?) {
               | 
            |
| 118 | 
                -        picker.dismiss(animated: true) {
               | 
            |
| 119 | 
                -//            if let sessionid = image.decodeQRCodeInImage() {
               | 
            |
| 120 | 
                -// self.addToGroup(sessionid)  | 
            |
| 121 | 
                -//            } else {
               | 
            |
| 122 | 
                -// FFToastView.showToast(inView: self.view, withText: "未检测到群二维码")  | 
            |
| 123 | 
                -// }  | 
            |
| 124 | 
                - }  | 
            |
| 125 | 
                - }  | 
            |
| 126 | 
                -  | 
            |
| 127 | 
                -    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
               | 
            |
| 128 | 
                - picker.dismissController()  | 
            |
| 129 | 
                - }  | 
            |
| 130 | 
                -  | 
            |
| 131 | 
                -}  | 
            |
| 68 | 
                +extension ScanQRViewController: NavigationBackViewController {}
               | 
            
                @@ -190,203 +190,203 @@  | 
            ||
| 190 | 190 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>  | 
            
| 191 | 191 | 
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>  | 
            
| 192 | 192 | 
                <subviews>  | 
            
| 193 | 
                - <view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="StI-0Q-fat">  | 
            |
| 194 | 
                - <rect key="frame" x="0.0" y="20" width="375" height="647"/>  | 
            |
| 193 | 
                + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="vQs-oc-uao">  | 
            |
| 194 | 
                + <rect key="frame" x="0.0" y="20" width="375" height="192"/>  | 
            |
| 195 | 195 | 
                <subviews>  | 
            
| 196 | 
                - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WTN-Zx-JKR">  | 
            |
| 196 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nRF-R0-LcP" userLabel="message system">  | 
            |
| 197 | 197 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>  | 
            
| 198 | 
                + <subviews>  | 
            |
| 199 | 
                + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="W1B-Rc-piS">  | 
            |
| 200 | 
                + <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>  | 
            |
| 201 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 202 | 
                + <constraints>  | 
            |
| 203 | 
                + <constraint firstAttribute="height" constant="64" id="Sh9-mX-758"/>  | 
            |
| 204 | 
                + </constraints>  | 
            |
| 205 | 
                + </button>  | 
            |
| 206 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-system" translatesAutoresizingMaskIntoConstraints="NO" id="PdF-av-quF">  | 
            |
| 207 | 
                + <rect key="frame" x="12" y="8" width="48" height="48"/>  | 
            |
| 208 | 
                + <constraints>  | 
            |
| 209 | 
                + <constraint firstAttribute="width" secondItem="PdF-av-quF" secondAttribute="height" id="X2X-ko-fTx"/>  | 
            |
| 210 | 
                + <constraint firstAttribute="width" constant="48" id="ozh-Fb-Dwl"/>  | 
            |
| 211 | 
                + </constraints>  | 
            |
| 212 | 
                + </imageView>  | 
            |
| 213 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="服务提醒" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7m9-4r-95l">  | 
            |
| 214 | 
                + <rect key="frame" x="70" y="22.5" width="65.5" height="19.5"/>  | 
            |
| 215 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 216 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 217 | 
                + <nil key="highlightedColor"/>  | 
            |
| 218 | 
                + </label>  | 
            |
| 219 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="dyn-zM-jdf">  | 
            |
| 220 | 
                + <rect key="frame" x="341" y="14" width="24" height="36"/>  | 
            |
| 221 | 
                + </imageView>  | 
            |
| 222 | 
                + <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="veG-mJ-Dsh">  | 
            |
| 223 | 
                + <rect key="frame" x="325" y="28" width="8" height="8"/>  | 
            |
| 224 | 
                + <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 225 | 
                + <constraints>  | 
            |
| 226 | 
                + <constraint firstAttribute="height" constant="8" id="OSl-kV-dhl"/>  | 
            |
| 227 | 
                + <constraint firstAttribute="width" constant="8" id="ojQ-4T-AHY"/>  | 
            |
| 228 | 
                + </constraints>  | 
            |
| 229 | 
                + <userDefinedRuntimeAttributes>  | 
            |
| 230 | 
                + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 231 | 
                + <real key="value" value="4"/>  | 
            |
| 232 | 
                + </userDefinedRuntimeAttribute>  | 
            |
| 233 | 
                + </userDefinedRuntimeAttributes>  | 
            |
| 234 | 
                + </view>  | 
            |
| 235 | 
                + </subviews>  | 
            |
| 198 | 236 | 
                <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 199 | 237 | 
                <constraints>  | 
            
| 200 | 
                - <constraint firstAttribute="height" constant="64" id="xeq-dk-WF7"/>  | 
            |
| 201 | 
                - </constraints>  | 
            |
| 202 | 
                - </button>  | 
            |
| 203 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-system" translatesAutoresizingMaskIntoConstraints="NO" id="PdF-av-quF">  | 
            |
| 204 | 
                - <rect key="frame" x="12" y="8" width="48" height="48"/>  | 
            |
| 205 | 
                - <constraints>  | 
            |
| 206 | 
                - <constraint firstAttribute="width" secondItem="PdF-av-quF" secondAttribute="height" id="X2X-ko-fTx"/>  | 
            |
| 207 | 
                - <constraint firstAttribute="width" constant="48" id="ozh-Fb-Dwl"/>  | 
            |
| 238 | 
                + <constraint firstItem="7m9-4r-95l" firstAttribute="leading" secondItem="PdF-av-quF" secondAttribute="trailing" constant="10" id="3Zc-bV-A1v"/>  | 
            |
| 239 | 
                + <constraint firstItem="7m9-4r-95l" firstAttribute="centerY" secondItem="nRF-R0-LcP" secondAttribute="centerY" id="4Uc-VE-e5u"/>  | 
            |
| 240 | 
                + <constraint firstAttribute="bottom" secondItem="W1B-Rc-piS" secondAttribute="bottom" id="ATc-VY-uV1"/>  | 
            |
| 241 | 
                + <constraint firstItem="dyn-zM-jdf" firstAttribute="centerY" secondItem="nRF-R0-LcP" secondAttribute="centerY" id="AgQ-Nz-FaV"/>  | 
            |
| 242 | 
                + <constraint firstAttribute="trailing" secondItem="dyn-zM-jdf" secondAttribute="trailing" constant="10" id="BuW-nY-yJ8"/>  | 
            |
| 243 | 
                + <constraint firstItem="PdF-av-quF" firstAttribute="leading" secondItem="nRF-R0-LcP" secondAttribute="leading" constant="12" id="CVF-7B-S39"/>  | 
            |
| 244 | 
                + <constraint firstItem="dyn-zM-jdf" firstAttribute="leading" secondItem="veG-mJ-Dsh" secondAttribute="trailing" constant="8" id="GCo-tj-G7p"/>  | 
            |
| 245 | 
                + <constraint firstItem="PdF-av-quF" firstAttribute="centerY" secondItem="nRF-R0-LcP" secondAttribute="centerY" id="KHj-j9-uOp"/>  | 
            |
| 246 | 
                + <constraint firstAttribute="height" constant="64" id="NR8-Hm-Hek"/>  | 
            |
| 247 | 
                + <constraint firstItem="W1B-Rc-piS" firstAttribute="leading" secondItem="nRF-R0-LcP" secondAttribute="leading" id="UxI-MO-gXc"/>  | 
            |
| 248 | 
                + <constraint firstItem="W1B-Rc-piS" firstAttribute="top" secondItem="nRF-R0-LcP" secondAttribute="top" id="Ysp-Kx-3q6"/>  | 
            |
| 249 | 
                + <constraint firstItem="veG-mJ-Dsh" firstAttribute="centerY" secondItem="nRF-R0-LcP" secondAttribute="centerY" id="pwl-I4-zYk"/>  | 
            |
| 250 | 
                + <constraint firstAttribute="trailing" secondItem="W1B-Rc-piS" secondAttribute="trailing" id="z9e-Kz-bqH"/>  | 
            |
| 208 | 251 | 
                </constraints>  | 
            
| 209 | 
                - </imageView>  | 
            |
| 210 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="服务提醒" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OGv-b6-6xR">  | 
            |
| 211 | 
                - <rect key="frame" x="70" y="22" width="66" height="20"/>  | 
            |
| 212 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 213 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 214 | 
                - <nil key="highlightedColor"/>  | 
            |
| 215 | 
                - </label>  | 
            |
| 216 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="mre-Tt-F0S">  | 
            |
| 217 | 
                - <rect key="frame" x="341" y="14" width="24" height="36"/>  | 
            |
| 218 | 
                - </imageView>  | 
            |
| 219 | 
                - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="T9q-a4-Ugc">  | 
            |
| 252 | 
                + </view>  | 
            |
| 253 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FvO-F8-npa" userLabel="message thumbup">  | 
            |
| 220 | 254 | 
                <rect key="frame" x="0.0" y="64" width="375" height="64"/>  | 
            
| 255 | 
                + <subviews>  | 
            |
| 256 | 
                + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cYK-SK-9WL">  | 
            |
| 257 | 
                + <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>  | 
            |
| 258 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 259 | 
                + <constraints>  | 
            |
| 260 | 
                + <constraint firstAttribute="height" constant="64" id="CYE-TV-8Ku"/>  | 
            |
| 261 | 
                + </constraints>  | 
            |
| 262 | 
                + </button>  | 
            |
| 263 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-thumpub" translatesAutoresizingMaskIntoConstraints="NO" id="Mdm-bD-HR2">  | 
            |
| 264 | 
                + <rect key="frame" x="12" y="8" width="48" height="48"/>  | 
            |
| 265 | 
                + <constraints>  | 
            |
| 266 | 
                + <constraint firstAttribute="width" constant="48" id="4Df-nG-nZr"/>  | 
            |
| 267 | 
                + <constraint firstAttribute="width" secondItem="Mdm-bD-HR2" secondAttribute="height" id="Doc-vC-DdB"/>  | 
            |
| 268 | 
                + </constraints>  | 
            |
| 269 | 
                + </imageView>  | 
            |
| 270 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="赞" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vFD-Hf-dPV" userLabel="赞">  | 
            |
| 271 | 
                + <rect key="frame" x="70" y="22.5" width="16.5" height="19.5"/>  | 
            |
| 272 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 273 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 274 | 
                + <nil key="highlightedColor"/>  | 
            |
| 275 | 
                + </label>  | 
            |
| 276 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="rWa-ZW-l2r">  | 
            |
| 277 | 
                + <rect key="frame" x="341" y="14" width="24" height="36"/>  | 
            |
| 278 | 
                + </imageView>  | 
            |
| 279 | 
                + <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iqd-Ji-zvi">  | 
            |
| 280 | 
                + <rect key="frame" x="325" y="28" width="8" height="8"/>  | 
            |
| 281 | 
                + <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 282 | 
                + <constraints>  | 
            |
| 283 | 
                + <constraint firstAttribute="height" constant="8" id="MLn-gz-qhL"/>  | 
            |
| 284 | 
                + <constraint firstAttribute="width" constant="8" id="vUg-zy-oPo"/>  | 
            |
| 285 | 
                + </constraints>  | 
            |
| 286 | 
                + <userDefinedRuntimeAttributes>  | 
            |
| 287 | 
                + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 288 | 
                + <real key="value" value="4"/>  | 
            |
| 289 | 
                + </userDefinedRuntimeAttribute>  | 
            |
| 290 | 
                + </userDefinedRuntimeAttributes>  | 
            |
| 291 | 
                + </view>  | 
            |
| 292 | 
                + </subviews>  | 
            |
| 221 | 293 | 
                <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 222 | 294 | 
                <constraints>  | 
            
| 223 | 
                - <constraint firstAttribute="height" constant="64" id="SZg-wA-Ma3"/>  | 
            |
| 224 | 
                - </constraints>  | 
            |
| 225 | 
                - </button>  | 
            |
| 226 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-thumpub" translatesAutoresizingMaskIntoConstraints="NO" id="NEm-bF-yno">  | 
            |
| 227 | 
                - <rect key="frame" x="12" y="72" width="48" height="48"/>  | 
            |
| 228 | 
                - <constraints>  | 
            |
| 229 | 
                - <constraint firstAttribute="width" constant="48" id="jD0-aO-eUu"/>  | 
            |
| 230 | 
                - <constraint firstAttribute="width" secondItem="NEm-bF-yno" secondAttribute="height" id="snW-w9-7b3"/>  | 
            |
| 231 | 
                - </constraints>  | 
            |
| 232 | 
                - </imageView>  | 
            |
| 233 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="8VZ-dR-b6z">  | 
            |
| 234 | 
                - <rect key="frame" x="341" y="78" width="24" height="36"/>  | 
            |
| 235 | 
                - </imageView>  | 
            |
| 236 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="赞" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J3p-B7-gMi">  | 
            |
| 237 | 
                - <rect key="frame" x="70" y="86" width="17" height="20"/>  | 
            |
| 238 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 239 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 240 | 
                - <nil key="highlightedColor"/>  | 
            |
| 241 | 
                - </label>  | 
            |
| 242 | 
                - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KVD-Az-tyJ">  | 
            |
| 243 | 
                - <rect key="frame" x="0.0" y="128" width="375" height="64"/>  | 
            |
| 244 | 
                - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 245 | 
                - <constraints>  | 
            |
| 246 | 
                - <constraint firstAttribute="height" constant="64" id="zcX-3o-C4B"/>  | 
            |
| 247 | 
                - </constraints>  | 
            |
| 248 | 
                - </button>  | 
            |
| 249 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-comment" translatesAutoresizingMaskIntoConstraints="NO" id="cgb-6k-KQJ">  | 
            |
| 250 | 
                - <rect key="frame" x="12" y="136" width="48" height="48"/>  | 
            |
| 251 | 
                - <constraints>  | 
            |
| 252 | 
                - <constraint firstAttribute="width" secondItem="cgb-6k-KQJ" secondAttribute="height" id="FhM-W8-0eM"/>  | 
            |
| 253 | 
                - <constraint firstAttribute="width" constant="48" id="Kmf-oj-nfI"/>  | 
            |
| 254 | 
                - </constraints>  | 
            |
| 255 | 
                - </imageView>  | 
            |
| 256 | 
                - <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="hJe-J2-RpF">  | 
            |
| 257 | 
                - <rect key="frame" x="341" y="142" width="24" height="36"/>  | 
            |
| 258 | 
                - </imageView>  | 
            |
| 259 | 
                - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="评论" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6fy-0a-WYd">  | 
            |
| 260 | 
                - <rect key="frame" x="70" y="150" width="33" height="20"/>  | 
            |
| 261 | 
                - <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 262 | 
                - <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 263 | 
                - <nil key="highlightedColor"/>  | 
            |
| 264 | 
                - </label>  | 
            |
| 265 | 
                - <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oLf-Xb-QSv">  | 
            |
| 266 | 
                - <rect key="frame" x="325" y="28" width="8" height="8"/>  | 
            |
| 267 | 
                - <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 268 | 
                - <constraints>  | 
            |
| 269 | 
                - <constraint firstAttribute="height" constant="8" id="8PB-CF-AvI"/>  | 
            |
| 270 | 
                - <constraint firstAttribute="width" constant="8" id="WJH-jN-MFb"/>  | 
            |
| 271 | 
                - </constraints>  | 
            |
| 272 | 
                - <userDefinedRuntimeAttributes>  | 
            |
| 273 | 
                - <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 274 | 
                - <real key="value" value="4"/>  | 
            |
| 275 | 
                - </userDefinedRuntimeAttribute>  | 
            |
| 276 | 
                - </userDefinedRuntimeAttributes>  | 
            |
| 277 | 
                - </view>  | 
            |
| 278 | 
                - <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="R8U-gK-x5D">  | 
            |
| 279 | 
                - <rect key="frame" x="325" y="92" width="8" height="8"/>  | 
            |
| 280 | 
                - <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 281 | 
                - <constraints>  | 
            |
| 282 | 
                - <constraint firstAttribute="height" constant="8" id="pvk-DY-af3"/>  | 
            |
| 283 | 
                - <constraint firstAttribute="width" constant="8" id="y72-go-9Lu"/>  | 
            |
| 284 | 
                - </constraints>  | 
            |
| 285 | 
                - <userDefinedRuntimeAttributes>  | 
            |
| 286 | 
                - <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 287 | 
                - <real key="value" value="4"/>  | 
            |
| 288 | 
                - </userDefinedRuntimeAttribute>  | 
            |
| 289 | 
                - </userDefinedRuntimeAttributes>  | 
            |
| 290 | 
                - </view>  | 
            |
| 291 | 
                - <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Qi9-c7-GCt">  | 
            |
| 292 | 
                - <rect key="frame" x="325" y="156" width="8" height="8"/>  | 
            |
| 293 | 
                - <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 294 | 
                - <constraints>  | 
            |
| 295 | 
                - <constraint firstAttribute="height" constant="8" id="d1V-XC-UJk"/>  | 
            |
| 296 | 
                - <constraint firstAttribute="width" constant="8" id="wcE-da-Ggi"/>  | 
            |
| 297 | 
                - </constraints>  | 
            |
| 298 | 
                - <userDefinedRuntimeAttributes>  | 
            |
| 299 | 
                - <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 300 | 
                - <real key="value" value="4"/>  | 
            |
| 301 | 
                - </userDefinedRuntimeAttribute>  | 
            |
| 302 | 
                - </userDefinedRuntimeAttributes>  | 
            |
| 303 | 
                - </view>  | 
            |
| 304 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LMK-Y1-Qex">  | 
            |
| 305 | 
                - <rect key="frame" x="70" y="63.5" width="305" height="0.5"/>  | 
            |
| 306 | 
                - <color key="backgroundColor" red="0.90588235289999997" green="0.90588235289999997" blue="0.90588235289999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 307 | 
                - <constraints>  | 
            |
| 308 | 
                - <constraint firstAttribute="height" constant="0.5" id="ygP-zr-Y2l"/>  | 
            |
| 295 | 
                + <constraint firstItem="rWa-ZW-l2r" firstAttribute="centerY" secondItem="FvO-F8-npa" secondAttribute="centerY" id="31J-Kc-V4M"/>  | 
            |
| 296 | 
                + <constraint firstItem="cYK-SK-9WL" firstAttribute="top" secondItem="FvO-F8-npa" secondAttribute="top" id="43p-Ol-SCA"/>  | 
            |
| 297 | 
                + <constraint firstItem="vFD-Hf-dPV" firstAttribute="centerY" secondItem="FvO-F8-npa" secondAttribute="centerY" id="FRm-10-cuU"/>  | 
            |
| 298 | 
                + <constraint firstItem="iqd-Ji-zvi" firstAttribute="centerY" secondItem="FvO-F8-npa" secondAttribute="centerY" id="H7y-qI-qAP"/>  | 
            |
| 299 | 
                + <constraint firstItem="Mdm-bD-HR2" firstAttribute="centerY" secondItem="FvO-F8-npa" secondAttribute="centerY" id="TtU-kN-5jV"/>  | 
            |
| 300 | 
                + <constraint firstAttribute="height" constant="64" id="Uhv-Ry-4pQ"/>  | 
            |
| 301 | 
                + <constraint firstItem="rWa-ZW-l2r" firstAttribute="leading" secondItem="iqd-Ji-zvi" secondAttribute="trailing" constant="8" id="bcO-40-lkC"/>  | 
            |
| 302 | 
                + <constraint firstItem="vFD-Hf-dPV" firstAttribute="leading" secondItem="Mdm-bD-HR2" secondAttribute="trailing" constant="10" id="c1Q-w8-1iV"/>  | 
            |
| 303 | 
                + <constraint firstAttribute="trailing" secondItem="rWa-ZW-l2r" secondAttribute="trailing" constant="10" id="f1H-lD-Bhp"/>  | 
            |
| 304 | 
                + <constraint firstItem="cYK-SK-9WL" firstAttribute="leading" secondItem="FvO-F8-npa" secondAttribute="leading" id="hT5-QW-acn"/>  | 
            |
| 305 | 
                + <constraint firstAttribute="bottom" secondItem="cYK-SK-9WL" secondAttribute="bottom" id="il0-Dm-SVq"/>  | 
            |
| 306 | 
                + <constraint firstAttribute="trailing" secondItem="cYK-SK-9WL" secondAttribute="trailing" id="j9y-uz-ARx"/>  | 
            |
| 307 | 
                + <constraint firstItem="Mdm-bD-HR2" firstAttribute="leading" secondItem="FvO-F8-npa" secondAttribute="leading" constant="12" id="vD8-AI-AAE"/>  | 
            |
| 309 | 308 | 
                </constraints>  | 
            
| 310 | 309 | 
                </view>  | 
            
| 311 | 
                - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gIo-ms-963">  | 
            |
| 312 | 
                - <rect key="frame" x="70" y="127.5" width="305" height="0.5"/>  | 
            |
| 313 | 
                - <color key="backgroundColor" red="0.90588235289999997" green="0.90588235289999997" blue="0.90588235289999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 310 | 
                + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Org-mm-8ZH" userLabel="message comment">  | 
            |
| 311 | 
                + <rect key="frame" x="0.0" y="128" width="375" height="64"/>  | 
            |
| 312 | 
                + <subviews>  | 
            |
| 313 | 
                + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pAl-ew-Vda">  | 
            |
| 314 | 
                + <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>  | 
            |
| 315 | 
                + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 316 | 
                + <constraints>  | 
            |
| 317 | 
                + <constraint firstAttribute="height" constant="64" id="Dnh-NK-K7H"/>  | 
            |
| 318 | 
                + </constraints>  | 
            |
| 319 | 
                + </button>  | 
            |
| 320 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="message-comment" translatesAutoresizingMaskIntoConstraints="NO" id="0Ga-dC-0cj">  | 
            |
| 321 | 
                + <rect key="frame" x="12" y="8" width="48" height="48"/>  | 
            |
| 322 | 
                + <constraints>  | 
            |
| 323 | 
                + <constraint firstAttribute="width" constant="48" id="Hcr-cI-PAb"/>  | 
            |
| 324 | 
                + <constraint firstAttribute="width" secondItem="0Ga-dC-0cj" secondAttribute="height" id="sQe-Iz-UsK"/>  | 
            |
| 325 | 
                + </constraints>  | 
            |
| 326 | 
                + </imageView>  | 
            |
| 327 | 
                + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="评论" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OqS-kg-xEo" userLabel="评论">  | 
            |
| 328 | 
                + <rect key="frame" x="70" y="22.5" width="33" height="19.5"/>  | 
            |
| 329 | 
                + <fontDescription key="fontDescription" type="system" pointSize="16"/>  | 
            |
| 330 | 
                + <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 331 | 
                + <nil key="highlightedColor"/>  | 
            |
| 332 | 
                + </label>  | 
            |
| 333 | 
                + <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="de8-5g-YER">  | 
            |
| 334 | 
                + <rect key="frame" x="341" y="14" width="24" height="36"/>  | 
            |
| 335 | 
                + </imageView>  | 
            |
| 336 | 
                + <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ywg-9R-Fz9">  | 
            |
| 337 | 
                + <rect key="frame" x="325" y="28" width="8" height="8"/>  | 
            |
| 338 | 
                + <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 339 | 
                + <constraints>  | 
            |
| 340 | 
                + <constraint firstAttribute="width" constant="8" id="ZOh-7N-i3b"/>  | 
            |
| 341 | 
                + <constraint firstAttribute="height" constant="8" id="fXX-l3-MG3"/>  | 
            |
| 342 | 
                + </constraints>  | 
            |
| 343 | 
                + <userDefinedRuntimeAttributes>  | 
            |
| 344 | 
                + <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">  | 
            |
| 345 | 
                + <real key="value" value="4"/>  | 
            |
| 346 | 
                + </userDefinedRuntimeAttribute>  | 
            |
| 347 | 
                + </userDefinedRuntimeAttributes>  | 
            |
| 348 | 
                + </view>  | 
            |
| 349 | 
                + </subviews>  | 
            |
| 350 | 
                + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 314 | 351 | 
                <constraints>  | 
            
| 315 | 
                - <constraint firstAttribute="height" constant="0.5" id="VfL-Rd-QTP"/>  | 
            |
| 352 | 
                + <constraint firstItem="OqS-kg-xEo" firstAttribute="centerY" secondItem="Org-mm-8ZH" secondAttribute="centerY" id="14q-Ka-Vk5"/>  | 
            |
| 353 | 
                + <constraint firstItem="pAl-ew-Vda" firstAttribute="top" secondItem="Org-mm-8ZH" secondAttribute="top" id="2Su-bl-RDw"/>  | 
            |
| 354 | 
                + <constraint firstItem="Ywg-9R-Fz9" firstAttribute="centerY" secondItem="Org-mm-8ZH" secondAttribute="centerY" id="9LY-bT-Hr2"/>  | 
            |
| 355 | 
                + <constraint firstAttribute="trailing" secondItem="de8-5g-YER" secondAttribute="trailing" constant="10" id="Aap-8M-fAT"/>  | 
            |
| 356 | 
                + <constraint firstAttribute="trailing" secondItem="pAl-ew-Vda" secondAttribute="trailing" id="ILI-UR-Vba"/>  | 
            |
| 357 | 
                + <constraint firstItem="OqS-kg-xEo" firstAttribute="leading" secondItem="0Ga-dC-0cj" secondAttribute="trailing" constant="10" id="JTR-w3-YbN"/>  | 
            |
| 358 | 
                + <constraint firstAttribute="bottom" secondItem="pAl-ew-Vda" secondAttribute="bottom" id="Klx-LC-YwX"/>  | 
            |
| 359 | 
                + <constraint firstItem="0Ga-dC-0cj" firstAttribute="centerY" secondItem="Org-mm-8ZH" secondAttribute="centerY" id="NZO-sW-7w8"/>  | 
            |
| 360 | 
                + <constraint firstItem="de8-5g-YER" firstAttribute="centerY" secondItem="Org-mm-8ZH" secondAttribute="centerY" id="fWR-wS-1FO"/>  | 
            |
| 361 | 
                + <constraint firstItem="pAl-ew-Vda" firstAttribute="leading" secondItem="Org-mm-8ZH" secondAttribute="leading" id="hUt-K2-O5X"/>  | 
            |
| 362 | 
                + <constraint firstItem="de8-5g-YER" firstAttribute="leading" secondItem="Ywg-9R-Fz9" secondAttribute="trailing" constant="8" id="lwS-rD-Wv9"/>  | 
            |
| 363 | 
                + <constraint firstItem="0Ga-dC-0cj" firstAttribute="leading" secondItem="Org-mm-8ZH" secondAttribute="leading" constant="12" id="p4H-7I-g5Q"/>  | 
            |
| 364 | 
                + <constraint firstAttribute="height" constant="64" id="qf9-lo-sVB"/>  | 
            |
| 316 | 365 | 
                </constraints>  | 
            
| 317 | 366 | 
                </view>  | 
            
| 318 | 367 | 
                </subviews>  | 
            
| 319 | 
                - <color key="backgroundColor" red="0.94117647059999998" green="0.94117647059999998" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 320 | 
                - <constraints>  | 
            |
| 321 | 
                - <constraint firstItem="PdF-av-quF" firstAttribute="width" secondItem="PdF-av-quF" secondAttribute="height" id="1SJ-Yy-8rF"/>  | 
            |
| 322 | 
                - <constraint firstItem="KVD-Az-tyJ" firstAttribute="leading" secondItem="StI-0Q-fat" secondAttribute="leading" id="1Sn-Ha-d7i"/>  | 
            |
| 323 | 
                - <constraint firstAttribute="trailing" secondItem="KVD-Az-tyJ" secondAttribute="trailing" id="1UZ-ZG-q7u"/>  | 
            |
| 324 | 
                - <constraint firstItem="NEm-bF-yno" firstAttribute="leading" secondItem="T9q-a4-Ugc" secondAttribute="leading" constant="12" id="3CF-yv-4wf"/>  | 
            |
| 325 | 
                - <constraint firstItem="R8U-gK-x5D" firstAttribute="centerY" secondItem="8VZ-dR-b6z" secondAttribute="centerY" id="3Yc-1d-XRV"/>  | 
            |
| 326 | 
                - <constraint firstItem="LMK-Y1-Qex" firstAttribute="leading" secondItem="OGv-b6-6xR" secondAttribute="leading" id="5AB-ql-wr1"/>  | 
            |
| 327 | 
                - <constraint firstItem="NEm-bF-yno" firstAttribute="width" secondItem="NEm-bF-yno" secondAttribute="height" id="5NQ-kl-Eq5"/>  | 
            |
| 328 | 
                - <constraint firstItem="T9q-a4-Ugc" firstAttribute="leading" secondItem="StI-0Q-fat" secondAttribute="leading" id="638-dc-DJj"/>  | 
            |
| 329 | 
                - <constraint firstItem="mre-Tt-F0S" firstAttribute="centerY" secondItem="WTN-Zx-JKR" secondAttribute="centerY" id="7Gh-JK-xlV"/>  | 
            |
| 330 | 
                - <constraint firstItem="hJe-J2-RpF" firstAttribute="leading" secondItem="Qi9-c7-GCt" secondAttribute="trailing" constant="8" id="8cD-ux-8w4"/>  | 
            |
| 331 | 
                - <constraint firstItem="6fy-0a-WYd" firstAttribute="centerY" secondItem="cgb-6k-KQJ" secondAttribute="centerY" id="EAW-Sd-au8"/>  | 
            |
| 332 | 
                - <constraint firstItem="WTN-Zx-JKR" firstAttribute="leading" secondItem="StI-0Q-fat" secondAttribute="leading" id="Ej8-vW-ES1"/>  | 
            |
| 333 | 
                - <constraint firstItem="oLf-Xb-QSv" firstAttribute="centerY" secondItem="mre-Tt-F0S" secondAttribute="centerY" id="Fty-Is-89H"/>  | 
            |
| 334 | 
                - <constraint firstItem="hJe-J2-RpF" firstAttribute="trailing" secondItem="KVD-Az-tyJ" secondAttribute="trailing" constant="-10" id="HLp-UP-zd4"/>  | 
            |
| 335 | 
                - <constraint firstItem="WTN-Zx-JKR" firstAttribute="top" secondItem="StI-0Q-fat" secondAttribute="top" id="Hdq-cw-396"/>  | 
            |
| 336 | 
                - <constraint firstAttribute="trailing" secondItem="gIo-ms-963" secondAttribute="trailing" id="Hfb-BT-Y32"/>  | 
            |
| 337 | 
                - <constraint firstItem="6fy-0a-WYd" firstAttribute="leading" secondItem="cgb-6k-KQJ" secondAttribute="trailing" constant="10" id="IoR-Al-XZl"/>  | 
            |
| 338 | 
                - <constraint firstItem="gIo-ms-963" firstAttribute="bottom" secondItem="T9q-a4-Ugc" secondAttribute="bottom" id="Joq-MV-NEZ"/>  | 
            |
| 339 | 
                - <constraint firstItem="OGv-b6-6xR" firstAttribute="leading" secondItem="PdF-av-quF" secondAttribute="trailing" constant="10" id="K4D-BZ-8ZU"/>  | 
            |
| 340 | 
                - <constraint firstItem="Qi9-c7-GCt" firstAttribute="centerY" secondItem="hJe-J2-RpF" secondAttribute="centerY" id="LUZ-KU-t61"/>  | 
            |
| 341 | 
                - <constraint firstAttribute="trailing" secondItem="LMK-Y1-Qex" secondAttribute="trailing" id="LYk-HD-SVv"/>  | 
            |
| 342 | 
                - <constraint firstItem="OGv-b6-6xR" firstAttribute="centerY" secondItem="PdF-av-quF" secondAttribute="centerY" id="Obx-DC-2Ms"/>  | 
            |
| 343 | 
                - <constraint firstItem="hJe-J2-RpF" firstAttribute="centerY" secondItem="KVD-Az-tyJ" secondAttribute="centerY" id="PGD-Nd-FxL"/>  | 
            |
| 344 | 
                - <constraint firstItem="mre-Tt-F0S" firstAttribute="leading" secondItem="oLf-Xb-QSv" secondAttribute="trailing" constant="8" id="Pgo-iF-JpC"/>  | 
            |
| 345 | 
                - <constraint firstItem="T9q-a4-Ugc" firstAttribute="top" secondItem="WTN-Zx-JKR" secondAttribute="bottom" id="PiP-8o-hlq"/>  | 
            |
| 346 | 
                - <constraint firstItem="J3p-B7-gMi" firstAttribute="centerY" secondItem="NEm-bF-yno" secondAttribute="centerY" id="U2Q-xG-JKb"/>  | 
            |
| 347 | 
                - <constraint firstAttribute="trailing" secondItem="mre-Tt-F0S" secondAttribute="trailing" constant="10" id="Udt-Ur-CYo"/>  | 
            |
| 348 | 
                - <constraint firstItem="cgb-6k-KQJ" firstAttribute="width" secondItem="cgb-6k-KQJ" secondAttribute="height" id="VBI-e4-8KY"/>  | 
            |
| 349 | 
                - <constraint firstItem="NEm-bF-yno" firstAttribute="centerY" secondItem="T9q-a4-Ugc" secondAttribute="centerY" id="VqD-xD-ZFL"/>  | 
            |
| 350 | 
                - <constraint firstItem="NEm-bF-yno" firstAttribute="width" secondItem="NEm-bF-yno" secondAttribute="height" id="WcT-QB-dXH"/>  | 
            |
| 351 | 
                - <constraint firstItem="8VZ-dR-b6z" firstAttribute="leading" secondItem="R8U-gK-x5D" secondAttribute="trailing" constant="8" id="Zm2-DB-9qE"/>  | 
            |
| 352 | 
                - <constraint firstItem="LMK-Y1-Qex" firstAttribute="bottom" secondItem="WTN-Zx-JKR" secondAttribute="bottom" id="hKb-bb-8Re"/>  | 
            |
| 353 | 
                - <constraint firstItem="8VZ-dR-b6z" firstAttribute="trailing" secondItem="T9q-a4-Ugc" secondAttribute="trailing" constant="-10" id="hTL-Jt-Om6"/>  | 
            |
| 354 | 
                - <constraint firstItem="J3p-B7-gMi" firstAttribute="leading" secondItem="NEm-bF-yno" secondAttribute="trailing" constant="10" id="he6-3z-Xta"/>  | 
            |
| 355 | 
                - <constraint firstItem="cgb-6k-KQJ" firstAttribute="leading" secondItem="KVD-Az-tyJ" secondAttribute="leading" constant="12" id="hek-US-nb3"/>  | 
            |
| 356 | 
                - <constraint firstAttribute="trailing" secondItem="WTN-Zx-JKR" secondAttribute="trailing" id="hyd-J3-IAR"/>  | 
            |
| 357 | 
                - <constraint firstItem="cgb-6k-KQJ" firstAttribute="width" secondItem="cgb-6k-KQJ" secondAttribute="height" id="lpl-IR-20q"/>  | 
            |
| 358 | 
                - <constraint firstItem="cgb-6k-KQJ" firstAttribute="width" secondItem="cgb-6k-KQJ" secondAttribute="height" id="oTf-HF-3EN"/>  | 
            |
| 359 | 
                - <constraint firstAttribute="trailing" secondItem="T9q-a4-Ugc" secondAttribute="trailing" id="qPZ-lF-bJJ"/>  | 
            |
| 360 | 
                - <constraint firstItem="gIo-ms-963" firstAttribute="leading" secondItem="J3p-B7-gMi" secondAttribute="leading" id="s1V-MK-hGp"/>  | 
            |
| 361 | 
                - <constraint firstItem="8VZ-dR-b6z" firstAttribute="centerY" secondItem="T9q-a4-Ugc" secondAttribute="centerY" id="vww-WS-1e6"/>  | 
            |
| 362 | 
                - <constraint firstItem="PdF-av-quF" firstAttribute="leading" secondItem="StI-0Q-fat" secondAttribute="leading" constant="12" id="wD2-zK-Qfe"/>  | 
            |
| 363 | 
                - <constraint firstItem="cgb-6k-KQJ" firstAttribute="centerY" secondItem="KVD-Az-tyJ" secondAttribute="centerY" id="wow-yY-0cl"/>  | 
            |
| 364 | 
                - <constraint firstItem="KVD-Az-tyJ" firstAttribute="top" secondItem="T9q-a4-Ugc" secondAttribute="bottom" id="yi0-UM-hgK"/>  | 
            |
| 365 | 
                - <constraint firstItem="PdF-av-quF" firstAttribute="centerY" secondItem="WTN-Zx-JKR" secondAttribute="centerY" id="zfd-Gi-l2q"/>  | 
            |
| 366 | 
                - </constraints>  | 
            |
| 367 | 
                - </view>  | 
            |
| 368 | 
                + </stackView>  | 
            |
| 368 | 369 | 
                </subviews>  | 
            
| 369 | 
                - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>  | 
            |
| 370 | 
                + <color key="backgroundColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            |
| 370 | 371 | 
                <constraints>  | 
            
| 371 | 
                - <constraint firstItem="pk7-RT-o9s" firstAttribute="trailing" secondItem="StI-0Q-fat" secondAttribute="trailing" id="1mB-xr-CQ7"/>  | 
            |
| 372 | 
                - <constraint firstAttribute="bottom" secondItem="StI-0Q-fat" secondAttribute="bottom" id="DhK-nf-Lrh"/>  | 
            |
| 373 | 
                - <constraint firstItem="StI-0Q-fat" firstAttribute="leading" secondItem="pk7-RT-o9s" secondAttribute="leading" id="jFj-Ls-vJb"/>  | 
            |
| 374 | 
                - <constraint firstItem="StI-0Q-fat" firstAttribute="top" secondItem="pk7-RT-o9s" secondAttribute="top" id="xbs-D5-7iw"/>  | 
            |
| 372 | 
                + <constraint firstItem="vQs-oc-uao" firstAttribute="leading" secondItem="pk7-RT-o9s" secondAttribute="leading" id="WMt-Hu-L7D"/>  | 
            |
| 373 | 
                + <constraint firstItem="pk7-RT-o9s" firstAttribute="trailing" secondItem="vQs-oc-uao" secondAttribute="trailing" id="qWK-p3-7fO"/>  | 
            |
| 374 | 
                + <constraint firstItem="vQs-oc-uao" firstAttribute="top" secondItem="pk7-RT-o9s" secondAttribute="top" id="u3B-bZ-94D"/>  | 
            |
| 375 | 375 | 
                </constraints>  | 
            
| 376 | 376 | 
                <viewLayoutGuide key="safeArea" id="pk7-RT-o9s"/>  | 
            
| 377 | 377 | 
                </view>  | 
            
| 378 | 378 | 
                <connections>  | 
            
| 379 | 
                - <outlet property="commentBtn" destination="KVD-Az-tyJ" id="TaX-hY-vn2"/>  | 
            |
| 380 | 
                - <outlet property="commentUnreadTip" destination="Qi9-c7-GCt" id="xt8-kU-Ort"/>  | 
            |
| 381 | 
                - <outlet property="sysBtn" destination="WTN-Zx-JKR" id="j7o-gs-BXE"/>  | 
            |
| 382 | 
                - <outlet property="sysUnreadTip" destination="oLf-Xb-QSv" id="K9s-Ru-LqL"/>  | 
            |
| 383 | 
                - <outlet property="thumbupBtn" destination="T9q-a4-Ugc" id="f6h-aq-4F0"/>  | 
            |
| 384 | 
                - <outlet property="thumbupUnreadTip" destination="R8U-gK-x5D" id="Lxs-zK-zAs"/>  | 
            |
| 379 | 
                + <outlet property="commentBtn" destination="pAl-ew-Vda" id="3S2-SN-tES"/>  | 
            |
| 380 | 
                + <outlet property="commentUnreadTip" destination="Ywg-9R-Fz9" id="kdE-V6-bFR"/>  | 
            |
| 381 | 
                + <outlet property="sysBtn" destination="W1B-Rc-piS" id="7RM-xD-0Ix"/>  | 
            |
| 382 | 
                + <outlet property="sysUnreadTip" destination="veG-mJ-Dsh" id="lsK-b7-GGU"/>  | 
            |
| 383 | 
                + <outlet property="thumbupBtn" destination="cYK-SK-9WL" id="SpB-pC-x36"/>  | 
            |
| 384 | 
                + <outlet property="thumbupUnreadTip" destination="iqd-Ji-zvi" id="IDb-6y-Pp4"/>  | 
            |
| 385 | 385 | 
                </connections>  | 
            
| 386 | 386 | 
                </viewController>  | 
            
| 387 | 387 | 
                <placeholder placeholderIdentifier="IBFirstResponder" id="13z-ah-xbs" userLabel="First Responder" sceneMemberID="firstResponder"/>  | 
            
| 388 | 388 | 
                </objects>  | 
            
| 389 | 
                - <point key="canvasLocation" x="53.600000000000001" y="28.335832083958024"/>  | 
            |
| 389 | 
                + <point key="canvasLocation" x="-52" y="-133"/>  | 
            |
| 390 | 390 | 
                </scene>  | 
            
| 391 | 391 | 
                </scenes>  | 
            
| 392 | 392 | 
                <resources>  | 
            
                @@ -22,7 +22,7 @@ final class GroupCell: UITableViewCell {
               | 
            ||
| 22 | 22 | 
                     func setInfo(_ info: GroupItem) {
               | 
            
| 23 | 23 | 
                groupImageView.setImage(info.group_avatar, placeholder: UIImage(named: "Group\(info.group_default_avatar)"))  | 
            
| 24 | 24 | 
                groupNameLabel.text = info.group_name  | 
            
| 25 | 
                -// createTimeLabel.text = info.created_at  | 
            |
| 25 | 
                + createTimeLabel.text = info.create_at  | 
            |
| 26 | 26 | 
                photoNumLabel.text = "有\(info.group_photo_num)张照片"  | 
            
| 27 | 27 | 
                }  | 
            
| 28 | 28 | 
                }  | 
            
                @@ -32,7 +32,7 @@ final class MineFeedbackViewController: UIViewController {
               | 
            ||
| 32 | 32 | 
                /// storyboard button action  | 
            
| 33 | 33 | 
                 extension MineFeedbackViewController {
               | 
            
| 34 | 34 | 
                     @IBAction func sendFeedBack() {
               | 
            
| 35 | 
                - Toast.showActivity(message: "正在提交")  | 
            |
| 35 | 
                + Toast.showActivity(message: "正在提交中")  | 
            |
| 36 | 36 | 
                         feedbackAPI.submit(text: textView.text).subscribe(onCompleted: {[weak self] in
               | 
            
| 37 | 37 | 
                             guard let `self` = self else { return }
               | 
            
| 38 | 38 | 
                Toast.hide()  | 
            
                @@ -28,10 +28,10 @@ class PhotoDetailCommentCell: UITableViewCell {
               | 
            ||
| 28 | 28 | 
                }  | 
            
| 29 | 29 | 
                 | 
            
| 30 | 30 | 
                // MARK: init interface  | 
            
| 31 | 
                -    func setInfo(_ data: PhotoCommentItem) {
               | 
            |
| 32 | 
                -// headImage.setImageWithNullableURL(data.avatar, placeholderImage: defaultAvatar)  | 
            |
| 33 | 
                - name.text = data.nickname  | 
            |
| 34 | 
                - content.text = data.comment  | 
            |
| 35 | 
                -// time.text = data.create_at.getTimeInfoFromDate()  | 
            |
| 31 | 
                +    func setInfo(_ info: PhotoCommentItem) {
               | 
            |
| 32 | 
                + headImage.setImage(info.avatar, placeholder: UIImage.defaultAvatar)  | 
            |
| 33 | 
                + name.text = info.nickname  | 
            |
| 34 | 
                + content.text = info.comment  | 
            |
| 35 | 
                + time.text = info.create_at  | 
            |
| 36 | 36 | 
                }  | 
            
| 37 | 37 | 
                }  | 
            
                @@ -52,7 +52,7 @@ extension PhotoDetailCoordinator: PhotoDetailListViewModelDelegate {
               | 
            ||
| 52 | 52 | 
                     func didSelected() {
               | 
            
| 53 | 53 | 
                let vc = UIStoryboard.photoDetail.instantiateController(PhotoPreviewViewController.self)  | 
            
| 54 | 54 | 
                vc.viewModel = shareListViewModel  | 
            
| 55 | 
                - navigationController.pushViewController(vc, animated: true)  | 
            |
| 55 | 
                + photoDetailViewController.presentController(vc)  | 
            |
| 56 | 56 | 
                }  | 
            
| 57 | 57 | 
                }  | 
            
| 58 | 58 | 
                 | 
            
                @@ -47,21 +47,11 @@ final class PhotoPreviewViewController: UIViewController {
               | 
            ||
| 47 | 47 | 
                navigationController?.setNavigationBarHidden(false, animated: true)  | 
            
| 48 | 48 | 
                }  | 
            
| 49 | 49 | 
                 | 
            
| 50 | 
                -    @IBAction func download(_ sender: UIButton) {
               | 
            |
| 51 | 
                - guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell,  | 
            |
| 52 | 
                -            let image = cell.photoImage.image else {
               | 
            |
| 53 | 
                - // FFToastView.showToast(inView: view, withText: "未检测到图片")  | 
            |
| 54 | 
                - return  | 
            |
| 55 | 
                - }  | 
            |
| 56 | 
                -  | 
            |
| 57 | 
                - UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)  | 
            |
| 58 | 
                - }  | 
            |
| 59 | 
                -  | 
            |
| 60 | 50 | 
                     @objc func image(_ image: UIImage?, didFinishSavingWithError error: NSError?, contextInfo info: UnsafeMutableRawPointer) {
               | 
            
| 61 | 51 | 
                         if error != nil {
               | 
            
| 62 | 
                - // FFToastView.showToast(inView: view, withText: "保存图片失败")  | 
            |
| 52 | 
                + Toast.show(message: "保存照片失败")  | 
            |
| 63 | 53 | 
                         } else {
               | 
            
| 64 | 
                - // FFToastView.showImageToast(inView: view, withText: "已保存图片到相册", withImage: "提示弹窗-勾")  | 
            |
| 54 | 
                + Toast.show(message: "已保存照片到相册中", image: UIImage(named: "icon-success"))  | 
            |
| 65 | 55 | 
                }  | 
            
| 66 | 56 | 
                }  | 
            
| 67 | 57 | 
                }  | 
            
                @@ -105,6 +95,7 @@ extension PhotoPreviewViewController {
               | 
            ||
| 105 | 95 | 
                     @IBAction  func back() {
               | 
            
| 106 | 96 | 
                navigationController?.popViewController(animated: true)  | 
            
| 107 | 97 | 
                }  | 
            
| 98 | 
                +  | 
            |
| 108 | 99 | 
                     @IBAction func rotateTheImage(_ sender: UIButton) {
               | 
            
| 109 | 100 | 
                         guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell else {
               | 
            
| 110 | 101 | 
                return  | 
            
                @@ -127,7 +118,16 @@ extension PhotoPreviewViewController {
               | 
            ||
| 127 | 118 | 
                }  | 
            
| 128 | 119 | 
                }  | 
            
| 129 | 120 | 
                 | 
            
| 130 | 
                -  | 
            |
| 121 | 
                +    @IBAction func download(_ sender: UIButton) {
               | 
            |
| 122 | 
                + Toast.showActivity(message: "正在保存照片到相册")  | 
            |
| 123 | 
                + guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell,  | 
            |
| 124 | 
                +            let image = cell.photoImage.image else {
               | 
            |
| 125 | 
                + Toast.show(message: "未检测到照片")  | 
            |
| 126 | 
                + return  | 
            |
| 127 | 
                + }  | 
            |
| 128 | 
                +  | 
            |
| 129 | 
                + UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)  | 
            |
| 130 | 
                + }  | 
            |
| 131 | 131 | 
                }  | 
            
| 132 | 132 | 
                 | 
            
| 133 | 133 | 
                // MARK: UICollectionView delegate  |